diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /libs | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libs')
148 files changed, 0 insertions, 47776 deletions
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp deleted file mode 100644 index d1b7af3..0000000 --- a/libs/audioflinger/A2dpAudioInterface.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <math.h> - -#define LOG_NDEBUG 0 -#define LOG_TAG "A2dpAudioInterface" -#include <utils/Log.h> -#include <utils/String8.h> - -#include "A2dpAudioInterface.h" -#include "audio/liba2dp.h" - - -namespace android { - -// ---------------------------------------------------------------------------- - -A2dpAudioInterface::A2dpAudioInterface() : - mOutput(0) -{ -} - -A2dpAudioInterface::~A2dpAudioInterface() -{ - delete mOutput; -} - -status_t A2dpAudioInterface::initCheck() -{ - return 0; -} - -AudioStreamOut* A2dpAudioInterface::openOutputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) -{ - LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate); - Mutex::Autolock lock(mLock); - status_t err = 0; - - // only one output stream allowed - if (mOutput) { - if (status) - *status = -1; - return NULL; - } - - // create new output stream - A2dpAudioStreamOut* out = new A2dpAudioStreamOut(); - if ((err = out->set(format, channelCount, sampleRate)) == NO_ERROR) { - mOutput = out; - } else { - delete out; - } - - if (status) - *status = err; - return mOutput; -} - -AudioStreamIn* A2dpAudioInterface::openInputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status, - AudioSystem::audio_in_acoustics acoustics) -{ - if (status) - *status = -1; - return NULL; -} - -status_t A2dpAudioInterface::setMicMute(bool state) -{ - return 0; -} - -status_t A2dpAudioInterface::getMicMute(bool* state) -{ - return 0; -} - -status_t A2dpAudioInterface::setParameter(const char *key, const char *value) -{ - LOGD("setParameter %s,%s\n", key, value); - - if (!key || !value) - return -EINVAL; - - if (strcmp(key, "a2dp_sink_address") == 0) { - return mOutput->setAddress(value); - } - if (strcmp(key, "bluetooth_enabled") == 0 && - strcmp(value, "false") == 0) { - return mOutput->close(); - } - - return 0; -} - -status_t A2dpAudioInterface::setVoiceVolume(float v) -{ - return 0; -} - -status_t A2dpAudioInterface::setMasterVolume(float v) -{ - return 0; -} - -status_t A2dpAudioInterface::doRouting() -{ - return 0; -} - -status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args) -{ - return 0; -} - -// ---------------------------------------------------------------------------- - -A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() : - mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL), - mInitialized(false) -{ - // use any address by default - strncpy(mA2dpAddress, "00:00:00:00:00:00", sizeof(mA2dpAddress)); -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::set( - int format, int channels, uint32_t rate) -{ - LOGD("A2dpAudioStreamOut::set %d, %d, %d\n", format, channels, rate); - - // fix up defaults - if (format == 0) format = AudioSystem::PCM_16_BIT; - if (channels == 0) channels = channelCount(); - if (rate == 0) rate = sampleRate(); - - // check values - if ((format != AudioSystem::PCM_16_BIT) || - (channels != channelCount()) || - (rate != sampleRate())) - return BAD_VALUE; - - return NO_ERROR; -} - -A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut() -{ - close(); -} - -ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes) -{ - status_t status = NO_INIT; - size_t remaining = bytes; - - if (!mInitialized) { - status = a2dp_init(mA2dpAddress, 44100, 2, &mData); - if (status < 0) { - LOGE("a2dp_init failed err: %d\n", status); - goto Error; - } - mInitialized = true; - } - - while (remaining > 0) { - status = a2dp_write(mData, buffer, remaining); - if (status <= 0) { - LOGE("a2dp_write failed err: %d\n", status); - goto Error; - } - remaining -= status; - buffer = ((char *)buffer) + status; - } - - mStandby = false; - - return bytes; - -Error: - close(); - // Simulate audio output timing in case of error - usleep(bytes * 1000000 / frameSize() / sampleRate()); - - return status; -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::standby() -{ - int result = 0; - - if (!mStandby) { - result = a2dp_stop(mData); - if (result == 0) - mStandby = true; - } - - return result; -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address) -{ - if (strlen(address) < sizeof(mA2dpAddress)) - return -EINVAL; - - if (strcmp(address, mA2dpAddress)) { - strcpy(mA2dpAddress, address); - close(); - } - - return NO_ERROR; -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::close() -{ - if (mData) { - a2dp_cleanup(mData); - mData = NULL; - mInitialized = false; - } - return NO_ERROR; -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args) -{ - return NO_ERROR; -} - - -}; // namespace android diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h deleted file mode 100644 index 5bef5da..0000000 --- a/libs/audioflinger/A2dpAudioInterface.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef A2DP_AUDIO_HARDWARE_H -#define A2DP_AUDIO_HARDWARE_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/threads.h> - -#include <hardware_legacy/AudioHardwareBase.h> - - -namespace android { - -class A2dpAudioInterface : public AudioHardwareBase -{ - class A2dpAudioStreamOut; - -public: - A2dpAudioInterface(); - virtual ~A2dpAudioInterface(); - virtual status_t initCheck(); - - virtual status_t setVoiceVolume(float volume); - virtual status_t setMasterVolume(float volume); - - // mic mute - virtual status_t setMicMute(bool state); - virtual status_t getMicMute(bool* state); - - // Temporary interface, do not use - // TODO: Replace with a more generic key:value get/set mechanism - virtual status_t setParameter(const char *key, const char *value); - - // create I/O streams - virtual AudioStreamOut* openOutputStream( - int format=0, - int channelCount=0, - uint32_t sampleRate=0, - status_t *status=0); - - virtual AudioStreamIn* openInputStream( - int format, - int channelCount, - uint32_t sampleRate, - status_t *status, - AudioSystem::audio_in_acoustics acoustics); - -protected: - virtual status_t doRouting(); - virtual status_t dump(int fd, const Vector<String16>& args); - -private: - class A2dpAudioStreamOut : public AudioStreamOut { - public: - A2dpAudioStreamOut(); - virtual ~A2dpAudioStreamOut(); - status_t set(int format, - int channelCount, - uint32_t sampleRate); - virtual uint32_t sampleRate() const { return 44100; } - // SBC codec wants a multiple of 512 - virtual size_t bufferSize() const { return 512 * 20; } - virtual int channelCount() const { return 2; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return ((1000*bufferSize())/frameSize())/sampleRate() + 200; } - virtual status_t setVolume(float volume) { return INVALID_OPERATION; } - virtual ssize_t write(const void* buffer, size_t bytes); - status_t standby(); - status_t close(); - virtual status_t dump(int fd, const Vector<String16>& args); - - private: - friend class A2dpAudioInterface; - status_t setAddress(const char* address); - - private: - int mFd; - bool mStandby; - int mStartCount; - int mRetryCount; - char mA2dpAddress[20]; - void* mData; - bool mInitialized; - }; - - Mutex mLock; - A2dpAudioStreamOut* mOutput; -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // A2DP_AUDIO_HARDWARE_H diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk deleted file mode 100644 index 50d516b..0000000 --- a/libs/audioflinger/Android.mk +++ /dev/null @@ -1,56 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - AudioHardwareGeneric.cpp \ - AudioHardwareStub.cpp \ - AudioDumpInterface.cpp \ - AudioHardwareInterface.cpp - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libmedia \ - libhardware_legacy - -ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true) - LOCAL_CFLAGS += -DGENERIC_AUDIO -endif - -LOCAL_MODULE:= libaudiointerface - -include $(BUILD_STATIC_LIBRARY) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - AudioFlinger.cpp \ - AudioMixer.cpp.arm \ - AudioResampler.cpp.arm \ - AudioResamplerSinc.cpp.arm \ - AudioResamplerCubic.cpp.arm - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libmedia \ - libhardware_legacy - -ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true) - LOCAL_STATIC_LIBRARIES += libaudiointerface -else - LOCAL_SHARED_LIBRARIES += libaudio -endif - -LOCAL_MODULE:= libaudioflinger - -ifeq ($(BOARD_HAVE_BLUETOOTH),true) - LOCAL_SRC_FILES += A2dpAudioInterface.cpp - LOCAL_SHARED_LIBRARIES += liba2dp - LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP - LOCAL_C_INCLUDES += $(call include-path-for, bluez-libs) - LOCAL_C_INCLUDES += $(call include-path-for, bluez-utils) -endif - -include $(BUILD_SHARED_LIBRARY) diff --git a/libs/audioflinger/AudioBufferProvider.h b/libs/audioflinger/AudioBufferProvider.h deleted file mode 100644 index 1a467c7..0000000 --- a/libs/audioflinger/AudioBufferProvider.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_AUDIO_BUFFER_PROVIDER_H -#define ANDROID_AUDIO_BUFFER_PROVIDER_H - -#include <stdint.h> -#include <sys/types.h> -#include <utils/Errors.h> - -namespace android { -// ---------------------------------------------------------------------------- - -class AudioBufferProvider -{ -public: - - struct Buffer { - union { - void* raw; - short* i16; - int8_t* i8; - }; - size_t frameCount; - }; - - virtual status_t getNextBuffer(Buffer* buffer) = 0; - virtual void releaseBuffer(Buffer* buffer) = 0; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_AUDIO_BUFFER_PROVIDER_H diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp deleted file mode 100644 index b4940cb..0000000 --- a/libs/audioflinger/AudioDumpInterface.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* //device/servers/AudioFlinger/AudioDumpInterface.cpp -** -** Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_TAG "AudioFlingerDump" - -#include <stdint.h> -#include <sys/types.h> -#include <utils/Log.h> - -#include <stdlib.h> -#include <unistd.h> - -#include "AudioDumpInterface.h" - -namespace android { - -bool gFirst = true; // true if first write after a standby - -// ---------------------------------------------------------------------------- - -AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw) -{ - if(hw == 0) { - LOGE("Dump construct hw = 0"); - } - mFinalInterface = hw; - mStreamOut = 0; -} - - -AudioDumpInterface::~AudioDumpInterface() -{ - if(mFinalInterface) delete mFinalInterface; - if(mStreamOut) delete mStreamOut; -} - - -AudioStreamOut* AudioDumpInterface::openOutputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) -{ - AudioStreamOut* outFinal = mFinalInterface->openOutputStream(format, channelCount, sampleRate, status); - - if(outFinal) { - mStreamOut = new AudioStreamOutDump(outFinal); - return mStreamOut; - } else { - LOGE("Dump outFinal=0"); - return 0; - } -} - -// ---------------------------------------------------------------------------- - -AudioStreamOutDump::AudioStreamOutDump( AudioStreamOut* finalStream) -{ - mFinalStream = finalStream; - mOutFile = 0; -} - - -AudioStreamOutDump::~AudioStreamOutDump() -{ - Close(); - delete mFinalStream; -} - -ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes) -{ - ssize_t ret; - - ret = mFinalStream->write(buffer, bytes); - if(!mOutFile && gFirst) { - gFirst = false; - // check if dump file exist - mOutFile = fopen(FLINGER_DUMP_NAME, "r"); - if(mOutFile) { - fclose(mOutFile); - mOutFile = fopen(FLINGER_DUMP_NAME, "ab"); - } - } - if (mOutFile) { - fwrite(buffer, bytes, 1, mOutFile); - } - return ret; -} - -status_t AudioStreamOutDump::standby() -{ - Close(); - gFirst = true; - return mFinalStream->standby(); -} - - -void AudioStreamOutDump::Close(void) -{ - if(mOutFile) { - fclose(mOutFile); - mOutFile = 0; - } -} - -}; // namespace android diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h deleted file mode 100644 index 9a94102..0000000 --- a/libs/audioflinger/AudioDumpInterface.h +++ /dev/null @@ -1,97 +0,0 @@ -/* //device/servers/AudioFlinger/AudioDumpInterface.h -** -** Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef ANDROID_AUDIO_DUMP_INTERFACE_H -#define ANDROID_AUDIO_DUMP_INTERFACE_H - -#include <stdint.h> -#include <sys/types.h> - -#include <hardware_legacy/AudioHardwareBase.h> - -namespace android { - -#define FLINGER_DUMP_NAME "/data/FlingerOut.pcm" // name of file used for dump - -class AudioStreamOutDump : public AudioStreamOut { -public: - AudioStreamOutDump( AudioStreamOut* FinalStream); - ~AudioStreamOutDump(); - virtual ssize_t write(const void* buffer, size_t bytes); - - virtual uint32_t sampleRate() const { return mFinalStream->sampleRate(); } - virtual size_t bufferSize() const { return mFinalStream->bufferSize(); } - virtual int channelCount() const { return mFinalStream->channelCount(); } - virtual int format() const { return mFinalStream->format(); } - virtual uint32_t latency() const { return mFinalStream->latency(); } - virtual status_t setVolume(float volume) - { return mFinalStream->setVolume(volume); } - virtual status_t standby(); - virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalStream->dump(fd, args); } - void Close(void); - -private: - AudioStreamOut *mFinalStream; - FILE *mOutFile; // output file -}; - - -class AudioDumpInterface : public AudioHardwareBase -{ - -public: - AudioDumpInterface(AudioHardwareInterface* hw); - virtual AudioStreamOut* openOutputStream( - int format=0, - int channelCount=0, - uint32_t sampleRate=0, - status_t *status=0); - virtual ~AudioDumpInterface(); - - virtual status_t initCheck() - {return mFinalInterface->initCheck();} - virtual status_t setVoiceVolume(float volume) - {return mFinalInterface->setVoiceVolume(volume);} - virtual status_t setMasterVolume(float volume) - {return mFinalInterface->setMasterVolume(volume);} - - // mic mute - virtual status_t setMicMute(bool state) - {return mFinalInterface->setMicMute(state);} - virtual status_t getMicMute(bool* state) - {return mFinalInterface->getMicMute(state);} - - virtual status_t setParameter(const char* key, const char* value) - {return mFinalInterface->setParameter(key, value);} - - virtual AudioStreamIn* openInputStream( int format, int channelCount, uint32_t sampleRate, status_t *status, - AudioSystem::audio_in_acoustics acoustics) - {return mFinalInterface->openInputStream( format, channelCount, sampleRate, status, acoustics);} - - virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); } - -protected: - virtual status_t doRouting() {return mFinalInterface->setRouting(mMode, mRoutes[mMode]);} - - AudioHardwareInterface *mFinalInterface; - AudioStreamOutDump *mStreamOut; - -}; - -}; // namespace android - -#endif // ANDROID_AUDIO_DUMP_INTERFACE_H diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp deleted file mode 100644 index 557d93b..0000000 --- a/libs/audioflinger/AudioFlinger.cpp +++ /dev/null @@ -1,2471 +0,0 @@ -/* //device/include/server/AudioFlinger/AudioFlinger.cpp -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - - -#define LOG_TAG "AudioFlinger" -//#define LOG_NDEBUG 0 - -#include <math.h> -#include <signal.h> -#include <sys/time.h> -#include <sys/resource.h> - -#include <utils/IServiceManager.h> -#include <utils/Log.h> -#include <utils/Parcel.h> -#include <utils/IPCThreadState.h> -#include <utils/String16.h> -#include <utils/threads.h> - -#include <cutils/properties.h> - -#include <media/AudioTrack.h> -#include <media/AudioRecord.h> - -#include <private/media/AudioTrackShared.h> - -#include <hardware_legacy/AudioHardwareInterface.h> - -#include "AudioMixer.h" -#include "AudioFlinger.h" - -#ifdef WITH_A2DP -#include "A2dpAudioInterface.h" -#endif - -// ---------------------------------------------------------------------------- -// the sim build doesn't have gettid - -#ifndef HAVE_GETTID -# define gettid getpid -#endif - -// ---------------------------------------------------------------------------- - -namespace android { - -//static const nsecs_t kStandbyTimeInNsecs = seconds(3); -static const unsigned long kBufferRecoveryInUsecs = 2000; -static const unsigned long kMaxBufferRecoveryInUsecs = 20000; -static const float MAX_GAIN = 4096.0f; - -// retry counts for buffer fill timeout -// 50 * ~20msecs = 1 second -static const int8_t kMaxTrackRetries = 50; -static const int8_t kMaxTrackStartupRetries = 50; - -static const int kStartSleepTime = 30000; -static const int kStopSleepTime = 30000; - -// Maximum number of pending buffers allocated by OutputTrack::write() -static const uint8_t kMaxOutputTrackBuffers = 5; - - -#define AUDIOFLINGER_SECURITY_ENABLED 1 - -// ---------------------------------------------------------------------------- - -static bool recordingAllowed() { -#ifndef HAVE_ANDROID_OS - return true; -#endif -#if AUDIOFLINGER_SECURITY_ENABLED - if (getpid() == IPCThreadState::self()->getCallingPid()) return true; - bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO")); - if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO"); - return ok; -#else - if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO"))) - LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest"); - return true; -#endif -} - -static bool settingsAllowed() { -#ifndef HAVE_ANDROID_OS - return true; -#endif -#if AUDIOFLINGER_SECURITY_ENABLED - if (getpid() == IPCThreadState::self()->getCallingPid()) return true; - bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")); - if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS"); - return ok; -#else - if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"))) - LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest"); - return true; -#endif -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::AudioFlinger() - : BnAudioFlinger(), - mAudioHardware(0), mA2dpAudioInterface(0), - mA2dpEnabled(false), mA2dpEnabledReq(false), - mForcedSpeakerCount(0), mForcedRoute(0), mRouteRestoreTime(0), mMusicMuteSaved(false) -{ - mHardwareStatus = AUDIO_HW_IDLE; - mAudioHardware = AudioHardwareInterface::create(); - mHardwareStatus = AUDIO_HW_INIT; - if (mAudioHardware->initCheck() == NO_ERROR) { - // open 16-bit output stream for s/w mixer - mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; - status_t status; - AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); - mHardwareStatus = AUDIO_HW_IDLE; - if (hwOutput) { - mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE); - } else { - LOGE("Failed to initialize hardware output stream, status: %d", status); - } - -#ifdef WITH_A2DP - // Create A2DP interface - mA2dpAudioInterface = new A2dpAudioInterface(); - AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); - if (a2dpOutput) { - mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP); - if (hwOutput) { - uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate(); - MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread, - hwOutput->sampleRate(), - AudioSystem::PCM_16_BIT, - hwOutput->channelCount(), - frameCount); - mHardwareMixerThread->setOuputTrack(a2dpOutTrack); - } - } else { - LOGE("Failed to initialize A2DP output stream, status: %d", status); - } -#endif - - // FIXME - this should come from settings - setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); - setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); - setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL); - setMode(AudioSystem::MODE_NORMAL); - - setMasterVolume(1.0f); - setMasterMute(false); - - // Start record thread - mAudioRecordThread = new AudioRecordThread(mAudioHardware); - if (mAudioRecordThread != 0) { - mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO); - } - } else { - LOGE("Couldn't even initialize the stubbed audio hardware!"); - } - - char value[PROPERTY_VALUE_MAX]; - property_get("ro.audio.silent", value, "0"); - if (atoi(value)) { - LOGD("Silence is golden"); - setMasterMute(true); - } -} - -AudioFlinger::~AudioFlinger() -{ - if (mAudioRecordThread != 0) { - mAudioRecordThread->exit(); - mAudioRecordThread.clear(); - } - mHardwareMixerThread.clear(); - delete mAudioHardware; - // deleting mA2dpAudioInterface also deletes mA2dpOutput; -#ifdef WITH_A2DP - mA2dpMixerThread.clear(); - delete mA2dpAudioInterface; -#endif -} - - -#ifdef WITH_A2DP -void AudioFlinger::setA2dpEnabled(bool enable) -{ - LOGV_IF(enable, "set output to A2DP\n"); - LOGV_IF(!enable, "set output to hardware audio\n"); - - mA2dpEnabledReq = enable; - mA2dpMixerThread->wakeUp(); -} -#endif // WITH_A2DP - -bool AudioFlinger::streamForcedToSpeaker(int streamType) -{ - // NOTE that streams listed here must not be routed to A2DP by default: - // AudioSystem::routedToA2dpOutput(streamType) == false - return (streamType == AudioSystem::RING || - streamType == AudioSystem::ALARM || - streamType == AudioSystem::NOTIFICATION); -} - -status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - result.append("Clients:\n"); - for (size_t i = 0; i < mClients.size(); ++i) { - wp<Client> wClient = mClients.valueAt(i); - if (wClient != 0) { - sp<Client> client = wClient.promote(); - if (client != 0) { - snprintf(buffer, SIZE, " pid: %d\n", client->pid()); - result.append(buffer); - } - } - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - - -status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "Permission Denial: " - "can't dump AudioFlinger from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::dump(int fd, const Vector<String16>& args) -{ - if (checkCallingPermission(String16("android.permission.DUMP")) == false) { - dumpPermissionDenial(fd, args); - } else { - AutoMutex lock(&mLock); - - dumpClients(fd, args); - dumpInternals(fd, args); - mHardwareMixerThread->dump(fd, args); -#ifdef WITH_A2DP - mA2dpMixerThread->dump(fd, args); -#endif - - // dump record client - if (mAudioRecordThread != 0) mAudioRecordThread->dump(fd, args); - - if (mAudioHardware) { - mAudioHardware->dumpState(fd, args); - } - } - return NO_ERROR; -} - -// IAudioFlinger interface - - -sp<IAudioTrack> AudioFlinger::createTrack( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp<IMemory>& sharedBuffer, - status_t *status) -{ - sp<MixerThread::Track> track; - sp<TrackHandle> trackHandle; - sp<Client> client; - wp<Client> wclient; - status_t lStatus; - - if (streamType >= AudioSystem::NUM_STREAM_TYPES) { - LOGE("invalid stream type"); - lStatus = BAD_VALUE; - goto Exit; - } - - { - Mutex::Autolock _l(mLock); - - wclient = mClients.valueFor(pid); - - if (wclient != NULL) { - client = wclient.promote(); - } else { - client = new Client(this, pid); - mClients.add(pid, client); - } -#ifdef WITH_A2DP - if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) { - track = mA2dpMixerThread->createTrack(client, streamType, sampleRate, format, - channelCount, frameCount, sharedBuffer, &lStatus); - } else -#endif - { - track = mHardwareMixerThread->createTrack(client, streamType, sampleRate, format, - channelCount, frameCount, sharedBuffer, &lStatus); - } - if (track != NULL) { - trackHandle = new TrackHandle(track); - lStatus = NO_ERROR; - } - } - -Exit: - if(status) { - *status = lStatus; - } - return trackHandle; -} - -uint32_t AudioFlinger::sampleRate(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->sampleRate(); - } -#endif - return mHardwareMixerThread->sampleRate(); -} - -int AudioFlinger::channelCount(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->channelCount(); - } -#endif - return mHardwareMixerThread->channelCount(); -} - -int AudioFlinger::format(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->format(); - } -#endif - return mHardwareMixerThread->format(); -} - -size_t AudioFlinger::frameCount(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->frameCount(); - } -#endif - return mHardwareMixerThread->frameCount(); -} - -uint32_t AudioFlinger::latency(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->latency(); - } -#endif - return mHardwareMixerThread->latency(); -} - -status_t AudioFlinger::setMasterVolume(float value) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - // when hw supports master volume, don't scale in sw mixer - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - if (mAudioHardware->setMasterVolume(value) == NO_ERROR) { - value = 1.0f; - } - mHardwareStatus = AUDIO_HW_IDLE; - mHardwareMixerThread->setMasterVolume(value); -#ifdef WITH_A2DP - mA2dpMixerThread->setMasterVolume(value); -#endif - - return NO_ERROR; -} - -status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) -{ - status_t err = NO_ERROR; - - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) { - LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask); - return BAD_VALUE; - } - -#ifdef WITH_A2DP - LOGD("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(), IPCThreadState::self()->getCallingPid()); - if (mode == AudioSystem::MODE_NORMAL && - (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) { - AutoMutex lock(&mLock); - - bool enableA2dp = false; - if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) { - enableA2dp = true; - } - setA2dpEnabled(enableA2dp); - LOGV("setOutput done\n"); - } -#endif - - // do nothing if only A2DP routing is affected - mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP; - if (mask) { - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_GET_ROUTING; - uint32_t r; - err = mAudioHardware->getRouting(mode, &r); - if (err == NO_ERROR) { - r = (r & ~mask) | (routes & mask); - if (mode == AudioSystem::MODE_NORMAL || - (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) { - mSavedRoute = r; - r |= mForcedRoute; - LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute); - } - mHardwareStatus = AUDIO_HW_SET_ROUTING; - err = mAudioHardware->setRouting(mode, r); - } - mHardwareStatus = AUDIO_HW_IDLE; - } - return err; -} - -uint32_t AudioFlinger::getRouting(int mode) const -{ - uint32_t routes = 0; - if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) { - if (mode == AudioSystem::MODE_NORMAL || - (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) { - routes = mSavedRoute; - } else { - mHardwareStatus = AUDIO_HW_GET_ROUTING; - mAudioHardware->getRouting(mode, &routes); - mHardwareStatus = AUDIO_HW_IDLE; - } - } else { - LOGW("Illegal value: getRouting(%d)", mode); - } - return routes; -} - -status_t AudioFlinger::setMode(int mode) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) { - LOGW("Illegal value: setMode(%d)", mode); - return BAD_VALUE; - } - - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MODE; - status_t ret = mAudioHardware->setMode(mode); - mHardwareStatus = AUDIO_HW_IDLE; - return ret; -} - -int AudioFlinger::getMode() const -{ - int mode = AudioSystem::MODE_INVALID; - mHardwareStatus = AUDIO_HW_SET_MODE; - mAudioHardware->getMode(&mode); - mHardwareStatus = AUDIO_HW_IDLE; - return mode; -} - -status_t AudioFlinger::setMicMute(bool state) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MIC_MUTE; - status_t ret = mAudioHardware->setMicMute(state); - mHardwareStatus = AUDIO_HW_IDLE; - return ret; -} - -bool AudioFlinger::getMicMute() const -{ - bool state = AudioSystem::MODE_INVALID; - mHardwareStatus = AUDIO_HW_GET_MIC_MUTE; - mAudioHardware->getMicMute(&state); - mHardwareStatus = AUDIO_HW_IDLE; - return state; -} - -status_t AudioFlinger::setMasterMute(bool muted) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - mHardwareMixerThread->setMasterMute(muted); -#ifdef WITH_A2DP - mA2dpMixerThread->setMasterMute(muted); -#endif - return NO_ERROR; -} - -float AudioFlinger::masterVolume() const -{ - return mHardwareMixerThread->masterVolume(); -} - -bool AudioFlinger::masterMute() const -{ - return mHardwareMixerThread->masterMute(); -} - -status_t AudioFlinger::setStreamVolume(int stream, float value) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { - return BAD_VALUE; - } - - mHardwareMixerThread->setStreamVolume(stream, value); -#ifdef WITH_A2DP - mA2dpMixerThread->setStreamVolume(stream, value); -#endif - - status_t ret = NO_ERROR; - if (stream == AudioSystem::VOICE_CALL || - stream == AudioSystem::BLUETOOTH_SCO) { - - if (stream == AudioSystem::VOICE_CALL) { - value = (float)AudioSystem::logToLinear(value)/100.0f; - } else { // (type == AudioSystem::BLUETOOTH_SCO) - value = 1.0f; - } - - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_SET_VOICE_VOLUME; - ret = mAudioHardware->setVoiceVolume(value); - mHardwareStatus = AUDIO_HW_IDLE; - } - - return ret; -} - -status_t AudioFlinger::setStreamMute(int stream, bool muted) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { - return BAD_VALUE; - } - -#ifdef WITH_A2DP - mA2dpMixerThread->setStreamMute(stream, muted); -#endif - if (stream == AudioSystem::MUSIC) - { - AutoMutex lock(&mHardwareLock); - if (mForcedRoute != 0) - mMusicMuteSaved = muted; - else - mHardwareMixerThread->setStreamMute(stream, muted); - } else { - mHardwareMixerThread->setStreamMute(stream, muted); - } - - - - return NO_ERROR; -} - -float AudioFlinger::streamVolume(int stream) const -{ - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { - return 0.0f; - } - return mHardwareMixerThread->streamVolume(stream); -} - -bool AudioFlinger::streamMute(int stream) const -{ - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { - return true; - } - - if (stream == AudioSystem::MUSIC && mForcedRoute != 0) - { - return mMusicMuteSaved; - } - return mHardwareMixerThread->streamMute(stream); -} - -bool AudioFlinger::isMusicActive() const -{ - #ifdef WITH_A2DP - if (isA2dpEnabled()) { - return mA2dpMixerThread->isMusicActive(); - } - #endif - return mHardwareMixerThread->isMusicActive(); -} - -status_t AudioFlinger::setParameter(const char* key, const char* value) -{ - status_t result, result2; - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_SET_PARAMETER; - - LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid()); - result = mAudioHardware->setParameter(key, value); - if (mA2dpAudioInterface) { - result2 = mA2dpAudioInterface->setParameter(key, value); - if (result2) - result = result2; - } - mHardwareStatus = AUDIO_HW_IDLE; - return result; -} - -size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) -{ - return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount); -} - -void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) -{ - - LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mLock); - - sp<IBinder> binder = client->asBinder(); - if (mNotificationClients.indexOf(binder) < 0) { - LOGV("Adding notification client %p", binder.get()); - binder->linkToDeath(this); - mNotificationClients.add(binder); - client->a2dpEnabledChanged(isA2dpEnabled()); - } -} - -void AudioFlinger::binderDied(const wp<IBinder>& who) { - - LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mLock); - - IBinder *binder = who.unsafe_get(); - - if (binder != NULL) { - int index = mNotificationClients.indexOf(binder); - if (index >= 0) { - LOGV("Removing notification client %p", binder); - mNotificationClients.removeAt(index); - } - } -} - -void AudioFlinger::handleOutputSwitch() -{ - if (mA2dpEnabled != mA2dpEnabledReq) - { - Mutex::Autolock _l(mLock); - - if (mA2dpEnabled != mA2dpEnabledReq) - { - mA2dpEnabled = mA2dpEnabledReq; - SortedVector < sp<MixerThread::Track> > tracks; - SortedVector < wp<MixerThread::Track> > activeTracks; - - // We hold mA2dpMixerThread mLock already - Mutex::Autolock _l(mHardwareMixerThread->mLock); - - // Transfer tracks playing on MUSIC stream from one mixer to the other - if (mA2dpEnabled) { - mHardwareMixerThread->getTracks(tracks, activeTracks); - mA2dpMixerThread->putTracks(tracks, activeTracks); - } else { - mA2dpMixerThread->getTracks(tracks, activeTracks); - mHardwareMixerThread->putTracks(tracks, activeTracks); - } - - // Notify AudioSystem of the A2DP activation/deactivation - size_t size = mNotificationClients.size(); - for (size_t i = 0; i < size; i++) { - sp<IBinder> binder = mNotificationClients.itemAt(i).promote(); - if (binder != NULL) { - LOGV("Notifying output change to client %p", binder.get()); - sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder); - client->a2dpEnabledChanged(mA2dpEnabled); - } - } - - mHardwareMixerThread->wakeUp(); - } - } -} - -void AudioFlinger::removeClient(pid_t pid) -{ - LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mLock); - mClients.removeItem(pid); -} - -void AudioFlinger::wakeUp() -{ - mHardwareMixerThread->wakeUp(); -#ifdef WITH_A2DP - mA2dpMixerThread->wakeUp(); -#endif // WITH_A2DP -} - -bool AudioFlinger::isA2dpEnabled() const -{ - return mA2dpEnabledReq; -} - -void AudioFlinger::handleForcedSpeakerRoute(int command) -{ - switch(command) { - case ACTIVE_TRACK_ADDED: - { - AutoMutex lock(mHardwareLock); - if (mForcedSpeakerCount++ == 0) { - mRouteRestoreTime = 0; - mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC); - if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) { - LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER); - mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - mAudioHardware->setMasterVolume(0); - usleep(mHardwareMixerThread->latency()*1000); - mHardwareStatus = AUDIO_HW_SET_ROUTING; - mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER); - mHardwareStatus = AUDIO_HW_IDLE; - // delay track start so that audio hardware has time to siwtch routes - usleep(kStartSleepTime); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume()); - mHardwareStatus = AUDIO_HW_IDLE; - } - mForcedRoute = AudioSystem::ROUTE_SPEAKER; - } - LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount); - } - break; - case ACTIVE_TRACK_REMOVED: - { - AutoMutex lock(mHardwareLock); - if (mForcedSpeakerCount > 0){ - if (--mForcedSpeakerCount == 0) { - mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000); - } - LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount); - } else { - LOGE("mForcedSpeakerCount is already zero"); - } - } - break; - case CHECK_ROUTE_RESTORE_TIME: - case FORCE_ROUTE_RESTORE: - if (mRouteRestoreTime) { - AutoMutex lock(mHardwareLock); - if (mRouteRestoreTime && - (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) { - mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved); - mForcedRoute = 0; - if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) { - mHardwareStatus = AUDIO_HW_SET_ROUTING; - mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute); - mHardwareStatus = AUDIO_HW_IDLE; - LOGV("Route forced to Speaker OFF %08x", mSavedRoute); - } - mRouteRestoreTime = 0; - } - } - break; - } -} - - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType) - : Thread(false), - mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType), - mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0), - mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false), - mInWrite(false) -{ - mSampleRate = output->sampleRate(); - mChannelCount = output->channelCount(); - - // FIXME - Current mixer implementation only supports stereo output - if (mChannelCount == 1) { - LOGE("Invalid audio hardware channel count"); - } - - mFormat = output->format(); - mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t); - mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate()); - - // FIXME - Current mixer implementation only supports stereo output: Always - // Allocate a stereo buffer even if HW output is mono. - mMixBuffer = new int16_t[mFrameCount * 2]; - memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t)); -} - -AudioFlinger::MixerThread::~MixerThread() -{ - delete [] mMixBuffer; - delete mAudioMixer; -} - -status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args) -{ - dumpInternals(fd, args); - dumpTracks(fd, args); - return NO_ERROR; -} - -status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType); - result.append(buffer); - result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n"); - for (size_t i = 0; i < mTracks.size(); ++i) { - wp<Track> wTrack = mTracks[i]; - if (wTrack != 0) { - sp<Track> track = wTrack.promote(); - if (track != 0) { - track->dump(buffer, SIZE); - result.append(buffer); - } - } - } - - snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType); - result.append(buffer); - result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n"); - for (size_t i = 0; i < mActiveTracks.size(); ++i) { - wp<Track> wTrack = mTracks[i]; - if (wTrack != 0) { - sp<Track> track = wTrack.promote(); - if (track != 0) { - track->dump(buffer, SIZE); - result.append(buffer); - } - } - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType); - result.append(buffer); - snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames()); - result.append(buffer); - snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime)); - result.append(buffer); - snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites); - result.append(buffer); - snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites); - result.append(buffer); - snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite); - result.append(buffer); - snprintf(buffer, SIZE, "standby: %d\n", mStandby); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// Thread virtuals -bool AudioFlinger::MixerThread::threadLoop() -{ - unsigned long sleepTime = kBufferRecoveryInUsecs; - int16_t* curBuf = mMixBuffer; - Vector< sp<Track> > tracksToRemove; - size_t enabledTracks = 0; - nsecs_t standbyTime = systemTime(); - size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t); - nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2; - -#ifdef WITH_A2DP - bool outputTrackActive = false; -#endif - - do { - enabledTracks = 0; - { // scope for the mLock - - Mutex::Autolock _l(mLock); - -#ifdef WITH_A2DP - if (mOutputType == AudioSystem::AUDIO_OUTPUT_A2DP) { - mAudioFlinger->handleOutputSwitch(); - } - if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) { - if (outputTrackActive) { - mOutputTrack->stop(); - outputTrackActive = false; - } - } -#endif - - const SortedVector< wp<Track> >& activeTracks = mActiveTracks; - - // put audio hardware into standby after short delay - if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) { - // wait until we have something to do... - LOGV("Audio hardware entering standby, output %d\n", mOutputType); -// mAudioFlinger->mHardwareStatus = AUDIO_HW_STANDBY; - if (!mStandby) { - mOutput->standby(); - mStandby = true; - } - -#ifdef WITH_A2DP - if (outputTrackActive) { - mOutputTrack->stop(); - outputTrackActive = false; - } -#endif - if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { - mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE); - } -// mHardwareStatus = AUDIO_HW_IDLE; - // we're about to wait, flush the binder command buffer - IPCThreadState::self()->flushCommands(); - mWaitWorkCV.wait(mLock); - LOGV("Audio hardware exiting standby, output %d\n", mOutputType); - standbyTime = systemTime() + kStandbyTimeInNsecs; - continue; - } - - // Forced route to speaker is handled by hardware mixer thread - if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { - mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME); - } - - // find out which tracks need to be processed - size_t count = activeTracks.size(); - for (size_t i=0 ; i<count ; i++) { - sp<Track> t = activeTracks[i].promote(); - if (t == 0) continue; - - Track* const track = t.get(); - audio_track_cblk_t* cblk = track->cblk(); - - // The first time a track is added we wait - // for all its buffers to be filled before processing it - mAudioMixer->setActiveTrack(track->name()); - if (cblk->framesReady() && (track->isReady() || track->isStopped()) && - !track->isPaused()) - { - //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server); - - // compute volume for this track - int16_t left, right; - if (track->isMuted() || mMasterMute || track->isPausing()) { - left = right = 0; - if (track->isPausing()) { - LOGV("paused(%d)", track->name()); - track->setPaused(); - } - } else { - float typeVolume = mStreamTypes[track->type()].volume; - float v = mMasterVolume * typeVolume; - float v_clamped = v * cblk->volume[0]; - if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; - left = int16_t(v_clamped); - v_clamped = v * cblk->volume[1]; - if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; - right = int16_t(v_clamped); - } - - // XXX: these things DON'T need to be done each time - mAudioMixer->setBufferProvider(track); - mAudioMixer->enable(AudioMixer::MIXING); - - int param; - if ( track->mFillingUpStatus == Track::FS_FILLED) { - // no ramp for the first volume setting - track->mFillingUpStatus = Track::FS_ACTIVE; - if (track->mState == TrackBase::RESUMING) { - track->mState = TrackBase::ACTIVE; - param = AudioMixer::RAMP_VOLUME; - } else { - param = AudioMixer::VOLUME; - } - } else { - param = AudioMixer::RAMP_VOLUME; - } - mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left); - mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right); - mAudioMixer->setParameter( - AudioMixer::TRACK, - AudioMixer::FORMAT, track->format()); - mAudioMixer->setParameter( - AudioMixer::TRACK, - AudioMixer::CHANNEL_COUNT, track->channelCount()); - mAudioMixer->setParameter( - AudioMixer::RESAMPLE, - AudioMixer::SAMPLE_RATE, - int(cblk->sampleRate)); - - // reset retry count - track->mRetryCount = kMaxTrackRetries; - enabledTracks++; - } else { - //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server); - if (track->isStopped()) { - track->reset(); - } - if (track->isTerminated() || track->isStopped() || track->isPaused()) { - // We have consumed all the buffers of this track. - // Remove it from the list of active tracks. - LOGV("remove(%d) from active list", track->name()); - tracksToRemove.add(track); - } else { - // No buffers for this track. Give it a few chances to - // fill a buffer, then remove it from active list. - if (--(track->mRetryCount) <= 0) { - LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name()); - tracksToRemove.add(track); - } - } - // LOGV("disable(%d)", track->name()); - mAudioMixer->disable(AudioMixer::MIXING); - } - } - - // remove all the tracks that need to be... - count = tracksToRemove.size(); - if (UNLIKELY(count)) { - for (size_t i=0 ; i<count ; i++) { - const sp<Track>& track = tracksToRemove[i]; - removeActiveTrack(track); - if (track->isTerminated()) { - mTracks.remove(track); - deleteTrackName(track->mName); - } - } - } - } - - if (LIKELY(enabledTracks)) { - // mix buffers... - mAudioMixer->process(curBuf); - -#ifdef WITH_A2DP - if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) { - if (!outputTrackActive) { - LOGV("starting output track in mixer for output %d", mOutputType); - mOutputTrack->start(); - outputTrackActive = true; - } - mOutputTrack->write(curBuf, mFrameCount); - } -#endif - - // output audio to hardware - mLastWriteTime = systemTime(); - mInWrite = true; - mOutput->write(curBuf, mixBufferSize); - mNumWrites++; - mInWrite = false; - mStandby = false; - nsecs_t temp = systemTime(); - standbyTime = temp + kStandbyTimeInNsecs; - nsecs_t delta = temp - mLastWriteTime; - if (delta > maxPeriod) { - LOGW("write blocked for %llu msecs", ns2ms(delta)); - mNumDelayedWrites++; - } - sleepTime = kBufferRecoveryInUsecs; - } else { -#ifdef WITH_A2DP - if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) { - if (outputTrackActive) { - mOutputTrack->write(curBuf, 0); - if (mOutputTrack->bufferQueueEmpty()) { - mOutputTrack->stop(); - outputTrackActive = false; - } else { - standbyTime = systemTime() + kStandbyTimeInNsecs; - } - } - } -#endif - // There was nothing to mix this round, which means all - // active tracks were late. Sleep a little bit to give - // them another chance. If we're too late, the audio - // hardware will zero-fill for us. - //LOGV("no buffers - usleep(%lu)", sleepTime); - usleep(sleepTime); - if (sleepTime < kMaxBufferRecoveryInUsecs) { - sleepTime += kBufferRecoveryInUsecs; - } - } - - // finally let go of all our tracks, without the lock held - // since we can't guarantee the destructors won't acquire that - // same lock. - tracksToRemove.clear(); - } while (true); - - return false; -} - -status_t AudioFlinger::MixerThread::readyToRun() -{ - if (mSampleRate == 0) { - LOGE("No working audio driver found."); - return NO_INIT; - } - LOGI("AudioFlinger's thread ready to run for output %d", mOutputType); - return NO_ERROR; -} - -void AudioFlinger::MixerThread::onFirstRef() -{ - const size_t SIZE = 256; - char buffer[SIZE]; - - snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType); - - run(buffer, ANDROID_PRIORITY_URGENT_AUDIO); -} - - -sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack( - const sp<AudioFlinger::Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer, - status_t *status) -{ - sp<Track> track; - status_t lStatus; - - // Resampler implementation limits input sampling rate to 2 x output sampling rate. - if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) { - LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate); - lStatus = BAD_VALUE; - goto Exit; - } - - { - Mutex::Autolock _l(mLock); - - if (mSampleRate == 0) { - LOGE("Audio driver not initialized."); - lStatus = NO_INIT; - goto Exit; - } - - track = new Track(this, client, streamType, sampleRate, format, - channelCount, frameCount, sharedBuffer); - if (track->getCblk() == NULL) { - track.clear(); - lStatus = NO_MEMORY; - goto Exit; - } - mTracks.add(track); - lStatus = NO_ERROR; - } - -Exit: - if(status) { - *status = lStatus; - } - return track; -} - -void AudioFlinger::MixerThread::getTracks( - SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks) -{ - size_t size = mTracks.size(); - LOGV ("MixerThread::getTracks() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType, mTracks.size(), mActiveTracks.size()); - for (size_t i = 0; i < size; i++) { - sp<Track> t = mTracks[i]; - if (AudioSystem::routedToA2dpOutput(t->mStreamType)) { - tracks.add(t); - int j = mActiveTracks.indexOf(t); - if (j >= 0) { - t = mActiveTracks[j].promote(); - if (t != NULL) { - activeTracks.add(t); - } - } - } - } - - size = activeTracks.size(); - for (size_t i = 0; i < size; i++) { - removeActiveTrack(activeTracks[i]); - } - - size = tracks.size(); - for (size_t i = 0; i < size; i++) { - sp<Track> t = tracks[i]; - mTracks.remove(t); - deleteTrackName(t->name()); - } -} - -void AudioFlinger::MixerThread::putTracks( - SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks) -{ - - LOGV ("MixerThread::putTracks() for output %d, tracks.size %d, activeTracks.size %d", mOutputType, tracks.size(), activeTracks.size()); - - size_t size = tracks.size(); - for (size_t i = 0; i < size ; i++) { - sp<Track> t = tracks[i]; - int name = getTrackName(); - - if (name < 0) return; - - t->mName = name; - t->mMixerThread = this; - mTracks.add(t); - - int j = activeTracks.indexOf(t); - if (j >= 0) { - addActiveTrack(t); - } - } -} - -uint32_t AudioFlinger::MixerThread::sampleRate() const -{ - return mSampleRate; -} - -int AudioFlinger::MixerThread::channelCount() const -{ - return mChannelCount; -} - -int AudioFlinger::MixerThread::format() const -{ - return mFormat; -} - -size_t AudioFlinger::MixerThread::frameCount() const -{ - return mFrameCount; -} - -uint32_t AudioFlinger::MixerThread::latency() const -{ - if (mOutput) { - return mOutput->latency(); - } - else { - return 0; - } -} - -status_t AudioFlinger::MixerThread::setMasterVolume(float value) -{ - mMasterVolume = value; - return NO_ERROR; -} - -status_t AudioFlinger::MixerThread::setMasterMute(bool muted) -{ - mMasterMute = muted; - return NO_ERROR; -} - -float AudioFlinger::MixerThread::masterVolume() const -{ - return mMasterVolume; -} - -bool AudioFlinger::MixerThread::masterMute() const -{ - return mMasterMute; -} - -status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value) -{ - mStreamTypes[stream].volume = value; - return NO_ERROR; -} - -status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted) -{ - mStreamTypes[stream].mute = muted; - return NO_ERROR; -} - -float AudioFlinger::MixerThread::streamVolume(int stream) const -{ - return mStreamTypes[stream].volume; -} - -bool AudioFlinger::MixerThread::streamMute(int stream) const -{ - return mStreamTypes[stream].mute; -} - -bool AudioFlinger::MixerThread::isMusicActive() const -{ - size_t count = mActiveTracks.size(); - for (size_t i = 0 ; i < count ; ++i) { - sp<Track> t = mActiveTracks[i].promote(); - if (t == 0) continue; - Track* const track = t.get(); - if (t->mStreamType == AudioSystem::MUSIC) - return true; - } - return false; -} - -status_t AudioFlinger::MixerThread::addTrack(const sp<Track>& track) -{ - status_t status = ALREADY_EXISTS; - Mutex::Autolock _l(mLock); - - // 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)", track->name()); - } else { - track->mState = TrackBase::ACTIVE; - LOGV("? => ACTIVE (%d)", track->name()); - } - // set retry count for buffer fill - track->mRetryCount = kMaxTrackStartupRetries; - if (mActiveTracks.indexOf(track) < 0) { - // the track is newly added, make sure it fills up all its - // buffers before playing. This is to ensure the client will - // effectively get the latency it requested. - track->mFillingUpStatus = Track::FS_FILLING; - track->mResetDone = false; - addActiveTrack(track); - status = NO_ERROR; - } - - LOGV("mWaitWorkCV.broadcast"); - mWaitWorkCV.broadcast(); - - return status; -} - -void AudioFlinger::MixerThread::removeTrack(wp<Track> track, int name) -{ - Mutex::Autolock _l(mLock); - sp<Track> t = track.promote(); - if (t!=NULL && (t->mState <= TrackBase::STOPPED)) { - remove_track_l(track, name); - } -} - -void AudioFlinger::MixerThread::remove_track_l(wp<Track> track, int name) -{ - sp<Track> t = track.promote(); - if (t!=NULL) { - t->reset(); - } - deleteTrackName(name); - removeActiveTrack(track); - mWaitWorkCV.broadcast(); -} - -void AudioFlinger::MixerThread::destroyTrack(const sp<Track>& track) -{ - // NOTE: We're acquiring a strong reference on the track before - // acquiring the lock, this is to make sure removing it from - // mTracks won't cause the destructor to be called while the lock is - // held (note that technically, 'track' could be a reference to an item - // in mTracks, which is why we need to do this). - sp<Track> keep(track); - Mutex::Autolock _l(mLock); - track->mState = TrackBase::TERMINATED; - if (mActiveTracks.indexOf(track) < 0) { - LOGV("remove track (%d) and delete from mixer", track->name()); - mTracks.remove(track); - deleteTrackName(keep->name()); - } -} - - -void AudioFlinger::MixerThread::addActiveTrack(const wp<Track>& t) -{ - mActiveTracks.add(t); - - // Force routing to speaker for certain stream types - // The forced routing to speaker is managed by hardware mixer - if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { - sp<Track> track = t.promote(); - if (track == NULL) return; - - if (streamForcedToSpeaker(track->type())) { - mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED); - } - } -} - -void AudioFlinger::MixerThread::removeActiveTrack(const wp<Track>& t) -{ - mActiveTracks.remove(t); - - // Force routing to speaker for certain stream types - // The forced routing to speaker is managed by hardware mixer - if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { - sp<Track> track = t.promote(); - if (track == NULL) return; - - if (streamForcedToSpeaker(track->type())) { - mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED); - } - } -} - -int AudioFlinger::MixerThread::getTrackName() -{ - return mAudioMixer->getTrackName(); -} - -void AudioFlinger::MixerThread::deleteTrackName(int name) -{ - mAudioMixer->deleteTrackName(name); -} - -size_t AudioFlinger::MixerThread::getOutputFrameCount() -{ - return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t); -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::TrackBase::TrackBase( - const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp<IMemory>& sharedBuffer) - : RefBase(), - mMixerThread(mixerThread), - mClient(client), - mStreamType(streamType), - mFrameCount(0), - mState(IDLE), - mClientTid(-1), - mFormat(format), - mFlags(flags & ~SYSTEM_FLAGS_MASK) -{ - mName = mixerThread->getTrackName(); - LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid()); - if (mName < 0) { - LOGE("no more track names availlable"); - return; - } - - LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); - - // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); - size_t size = sizeof(audio_track_cblk_t); - size_t bufferSize = frameCount*channelCount*sizeof(int16_t); - if (sharedBuffer == 0) { - size += bufferSize; - } - - if (client != NULL) { - mCblkMemory = client->heap()->allocate(size); - if (mCblkMemory != 0) { - mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer()); - if (mCblk) { // construct the shared structure in-place. - new(mCblk) audio_track_cblk_t(); - // clear all buffers - mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; - if (sharedBuffer == 0) { - mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); - memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); - // Force underrun condition to avoid false underrun callback until first data is - // written to buffer - mCblk->flowControlFlag = 1; - } else { - mBuffer = sharedBuffer->pointer(); - } - mBufferEnd = (uint8_t *)mBuffer + bufferSize; - } - } else { - LOGE("not enough memory for AudioTrack size=%u", size); - client->heap()->dump("AudioTrack"); - return; - } - } else { - mCblk = (audio_track_cblk_t *)(new uint8_t[size]); - if (mCblk) { // construct the shared structure in-place. - new(mCblk) audio_track_cblk_t(); - // clear all buffers - mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; - mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); - memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); - // Force underrun condition to avoid false underrun callback until first data is - // written to buffer - mCblk->flowControlFlag = 1; - mBufferEnd = (uint8_t *)mBuffer + bufferSize; - } - } -} - -AudioFlinger::MixerThread::TrackBase::~TrackBase() -{ - if (mCblk) { - mCblk->~audio_track_cblk_t(); // destroy our shared-structure. - } - mCblkMemory.clear(); // and free the shared memory - mClient.clear(); -} - -void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer) -{ - buffer->raw = 0; - mFrameCount = buffer->frameCount; - step(); - buffer->frameCount = 0; -} - -bool AudioFlinger::MixerThread::TrackBase::step() { - bool result; - audio_track_cblk_t* cblk = this->cblk(); - - result = cblk->stepServer(mFrameCount); - if (!result) { - LOGV("stepServer failed acquiring cblk mutex"); - mFlags |= STEPSERVER_FAILED; - } - return result; -} - -void AudioFlinger::MixerThread::TrackBase::reset() { - audio_track_cblk_t* cblk = this->cblk(); - - cblk->user = 0; - cblk->server = 0; - cblk->userBase = 0; - cblk->serverBase = 0; - mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK); - LOGV("TrackBase::reset"); -} - -sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const -{ - return mCblkMemory; -} - -int AudioFlinger::MixerThread::TrackBase::sampleRate() const { - return mCblk->sampleRate; -} - -int AudioFlinger::MixerThread::TrackBase::channelCount() const { - return mCblk->channels; -} - -void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const { - audio_track_cblk_t* cblk = this->cblk(); - int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels; - int16_t *bufferEnd = bufferStart + frames * cblk->channels; - - // Check validity of returned pointer in case the track control block would have been corrupted. - if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) { - LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ - server %d, serverBase %d, user %d, userBase %d", - bufferStart, bufferEnd, mBuffer, mBufferEnd, - cblk->server, cblk->serverBase, cblk->user, cblk->userBase); - return 0; - } - - return bufferStart; -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::Track::Track( - const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer) - : TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, 0, sharedBuffer) -{ - mVolume[0] = 1.0f; - mVolume[1] = 1.0f; - mMute = false; - mSharedBuffer = sharedBuffer; -} - -AudioFlinger::MixerThread::Track::~Track() -{ - wp<Track> weak(this); // never create a strong ref from the dtor - mState = TERMINATED; - mMixerThread->removeTrack(weak, mName); -} - -void AudioFlinger::MixerThread::Track::destroy() -{ - mMixerThread->destroyTrack(this); -} - -void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size) -{ - snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n", - mName - AudioMixer::TRACK0, - (mClient == NULL) ? getpid() : mClient->pid(), - mStreamType, - mFormat, - mCblk->channels, - mFrameCount, - mState, - mMute, - mFillingUpStatus, - mCblk->sampleRate, - mCblk->volume[0], - mCblk->volume[1], - mCblk->server, - mCblk->user); -} - -status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer) -{ - audio_track_cblk_t* cblk = this->cblk(); - uint32_t framesReady; - uint32_t framesReq = buffer->frameCount; - - // Check if last stepServer failed, try to step now - if (mFlags & TrackBase::STEPSERVER_FAILED) { - if (!step()) goto getNextBuffer_exit; - LOGV("stepServer recovered"); - mFlags &= ~TrackBase::STEPSERVER_FAILED; - } - - framesReady = cblk->framesReady(); - - if (LIKELY(framesReady)) { - uint32_t s = cblk->server; - uint32_t bufferEnd = cblk->serverBase + cblk->frameCount; - - bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd; - if (framesReq > framesReady) { - framesReq = framesReady; - } - if (s + framesReq > bufferEnd) { - framesReq = bufferEnd - s; - } - - buffer->raw = getBuffer(s, framesReq); - if (buffer->raw == 0) goto getNextBuffer_exit; - - buffer->frameCount = framesReq; - return NO_ERROR; - } - -getNextBuffer_exit: - buffer->raw = 0; - buffer->frameCount = 0; - return NOT_ENOUGH_DATA; -} - -bool AudioFlinger::MixerThread::Track::isReady() const { - if (mFillingUpStatus != FS_FILLING) return true; - - if (mCblk->framesReady() >= mCblk->frameCount || - mCblk->forceReady) { - mFillingUpStatus = FS_FILLED; - mCblk->forceReady = 0; - LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType); - return true; - } - return false; -} - -status_t AudioFlinger::MixerThread::Track::start() -{ - LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType); - mMixerThread->addTrack(this); - return NO_ERROR; -} - -void AudioFlinger::MixerThread::Track::stop() -{ - LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType); - Mutex::Autolock _l(mMixerThread->mLock); - if (mState > STOPPED) { - mState = STOPPED; - // If the track is not active (PAUSED and buffers full), flush buffers - if (mMixerThread->mActiveTracks.indexOf(this) < 0) { - reset(); - } - LOGV("(> STOPPED) => STOPPED (%d)", mName); - } -} - -void AudioFlinger::MixerThread::Track::pause() -{ - LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mMixerThread->mLock); - if (mState == ACTIVE || mState == RESUMING) { - mState = PAUSING; - LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName); - } -} - -void AudioFlinger::MixerThread::Track::flush() -{ - LOGV("flush(%d)", mName); - Mutex::Autolock _l(mMixerThread->mLock); - if (mState != STOPPED && mState != PAUSED && mState != PAUSING) { - return; - } - // No point remaining in PAUSED state after a flush => go to - // STOPPED state - mState = STOPPED; - - // NOTE: reset() will reset cblk->user and cblk->server with - // the risk that at the same time, the AudioMixer is trying to read - // data. In this case, getNextBuffer() would return a NULL pointer - // as audio buffer => the AudioMixer code MUST always test that pointer - // returned by getNextBuffer() is not NULL! - reset(); -} - -void AudioFlinger::MixerThread::Track::reset() -{ - // Do not reset twice to avoid discarding data written just after a flush and before - // the audioflinger thread detects the track is stopped. - if (!mResetDone) { - TrackBase::reset(); - // Force underrun condition to avoid false underrun callback until first data is - // written to buffer - mCblk->flowControlFlag = 1; - mCblk->forceReady = 0; - mFillingUpStatus = FS_FILLING; - mResetDone = true; - } -} - -void AudioFlinger::MixerThread::Track::mute(bool muted) -{ - mMute = muted; -} - -void AudioFlinger::MixerThread::Track::setVolume(float left, float right) -{ - mVolume[0] = left; - mVolume[1] = right; -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::RecordTrack::RecordTrack( - const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags) - : TrackBase(mixerThread, client, streamType, sampleRate, format, - channelCount, frameCount, flags, 0), - mOverflow(false) -{ -} - -AudioFlinger::MixerThread::RecordTrack::~RecordTrack() -{ - mMixerThread->deleteTrackName(mName); -} - -status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) -{ - audio_track_cblk_t* cblk = this->cblk(); - uint32_t framesAvail; - uint32_t framesReq = buffer->frameCount; - - // Check if last stepServer failed, try to step now - if (mFlags & TrackBase::STEPSERVER_FAILED) { - if (!step()) goto getNextBuffer_exit; - LOGV("stepServer recovered"); - mFlags &= ~TrackBase::STEPSERVER_FAILED; - } - - framesAvail = cblk->framesAvailable_l(); - - if (LIKELY(framesAvail)) { - uint32_t s = cblk->server; - uint32_t bufferEnd = cblk->serverBase + cblk->frameCount; - - if (framesReq > framesAvail) { - framesReq = framesAvail; - } - if (s + framesReq > bufferEnd) { - framesReq = bufferEnd - s; - } - - buffer->raw = getBuffer(s, framesReq); - if (buffer->raw == 0) goto getNextBuffer_exit; - - buffer->frameCount = framesReq; - return NO_ERROR; - } - -getNextBuffer_exit: - buffer->raw = 0; - buffer->frameCount = 0; - return NOT_ENOUGH_DATA; -} - -status_t AudioFlinger::MixerThread::RecordTrack::start() -{ - return mMixerThread->mAudioFlinger->startRecord(this); -} - -void AudioFlinger::MixerThread::RecordTrack::stop() -{ - mMixerThread->mAudioFlinger->stopRecord(this); - TrackBase::reset(); - // Force overerrun condition to avoid false overrun callback until first data is - // read from buffer - mCblk->flowControlFlag = 1; -} - - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::OutputTrack::OutputTrack( - const sp<MixerThread>& mixerThread, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount) - : Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL), - mOutputMixerThread(mixerThread) -{ - - mCblk->out = 1; - mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); - mCblk->volume[0] = mCblk->volume[1] = 0x1000; - mOutBuffer.frameCount = 0; - mCblk->bufferTimeoutMs = 10; - - LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p", - mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd); - -} - -AudioFlinger::MixerThread::OutputTrack::~OutputTrack() -{ - stop(); -} - -status_t AudioFlinger::MixerThread::OutputTrack::start() -{ - status_t status = Track::start(); - - mRetryCount = 127; - return status; -} - -void AudioFlinger::MixerThread::OutputTrack::stop() -{ - Track::stop(); - clearBufferQueue(); - mOutBuffer.frameCount = 0; -} - -void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames) -{ - Buffer *pInBuffer; - Buffer inBuffer; - uint32_t channels = mCblk->channels; - - inBuffer.frameCount = frames; - inBuffer.i16 = data; - - if (mCblk->user == 0) { - if (mOutputMixerThread->isMusicActive()) { - mCblk->forceReady = 1; - LOGV("OutputTrack::start() force ready"); - } else if (mCblk->frameCount > frames){ - if (mBufferQueue.size() < kMaxOutputTrackBuffers) { - uint32_t startFrames = (mCblk->frameCount - frames); - LOGV("OutputTrack::start() write %d frames", startFrames); - pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[startFrames * channels]; - pInBuffer->frameCount = startFrames; - pInBuffer->i16 = pInBuffer->mBuffer; - memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t)); - mBufferQueue.add(pInBuffer); - } else { - LOGW ("OutputTrack::write() no more buffers"); - } - } - } - - while (1) { - // First write pending buffers, then new data - if (mBufferQueue.size()) { - pInBuffer = mBufferQueue.itemAt(0); - } else { - pInBuffer = &inBuffer; - } - - if (pInBuffer->frameCount == 0) { - break; - } - - if (mOutBuffer.frameCount == 0) { - mOutBuffer.frameCount = pInBuffer->frameCount; - if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) { - break; - } - } - - uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount; - memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t)); - mCblk->stepUser(outFrames); - pInBuffer->frameCount -= outFrames; - pInBuffer->i16 += outFrames * channels; - mOutBuffer.frameCount -= outFrames; - mOutBuffer.i16 += outFrames * channels; - - if (pInBuffer->frameCount == 0) { - if (mBufferQueue.size()) { - mBufferQueue.removeAt(0); - delete [] pInBuffer->mBuffer; - delete pInBuffer; - } else { - break; - } - } - } - - // If we could not write all frames, allocate a buffer and queue it for next time. - if (inBuffer.frameCount) { - if (mBufferQueue.size() < kMaxOutputTrackBuffers) { - pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels]; - pInBuffer->frameCount = inBuffer.frameCount; - pInBuffer->i16 = pInBuffer->mBuffer; - memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t)); - mBufferQueue.add(pInBuffer); - } else { - LOGW("OutputTrack::write() no more buffers"); - } - } - - // Calling write() with a 0 length buffer, means that no more data will be written: - // If no more buffers are pending, fill output track buffer to make sure it is started - // by output mixer. - if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) { - frames = mCblk->frameCount - mCblk->user; - pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[frames * channels]; - pInBuffer->frameCount = frames; - pInBuffer->i16 = pInBuffer->mBuffer; - memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t)); - mBufferQueue.add(pInBuffer); - } - -} - -status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer) -{ - int active; - int timeout = 0; - status_t result; - audio_track_cblk_t* cblk = mCblk; - uint32_t framesReq = buffer->frameCount; - - LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server); - buffer->frameCount = 0; - - uint32_t framesAvail = cblk->framesAvailable(); - - if (framesAvail == 0) { - return AudioTrack::NO_MORE_BUFFERS; - } - - if (framesReq > framesAvail) { - framesReq = framesAvail; - } - - uint32_t u = cblk->user; - uint32_t bufferEnd = cblk->userBase + cblk->frameCount; - - if (u + framesReq > bufferEnd) { - framesReq = bufferEnd - u; - } - - buffer->frameCount = framesReq; - buffer->raw = (void *)cblk->buffer(u); - return NO_ERROR; -} - - -void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue() -{ - size_t size = mBufferQueue.size(); - Buffer *pBuffer; - - for (size_t i = 0; i < size; i++) { - pBuffer = mBufferQueue.itemAt(i); - delete [] pBuffer->mBuffer; - delete pBuffer; - } - mBufferQueue.clear(); -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid) - : RefBase(), - mAudioFlinger(audioFlinger), - mMemoryDealer(new MemoryDealer(1024*1024)), - mPid(pid) -{ - // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer -} - -AudioFlinger::Client::~Client() -{ - mAudioFlinger->removeClient(mPid); -} - -const sp<MemoryDealer>& AudioFlinger::Client::heap() const -{ - return mMemoryDealer; -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track) - : BnAudioTrack(), - mTrack(track) -{ -} - -AudioFlinger::TrackHandle::~TrackHandle() { - // just stop the track on deletion, associated resources - // will be freed from the main thread once all pending buffers have - // been played. Unless it's not in the active track list, in which - // case we free everything now... - mTrack->destroy(); -} - -status_t AudioFlinger::TrackHandle::start() { - return mTrack->start(); -} - -void AudioFlinger::TrackHandle::stop() { - mTrack->stop(); -} - -void AudioFlinger::TrackHandle::flush() { - mTrack->flush(); -} - -void AudioFlinger::TrackHandle::mute(bool e) { - mTrack->mute(e); -} - -void AudioFlinger::TrackHandle::pause() { - mTrack->pause(); -} - -void AudioFlinger::TrackHandle::setVolume(float left, float right) { - mTrack->setVolume(left, right); -} - -sp<IMemory> AudioFlinger::TrackHandle::getCblk() const { - return mTrack->getCblk(); -} - -status_t AudioFlinger::TrackHandle::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - return BnAudioTrack::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- - -sp<IAudioRecord> AudioFlinger::openRecord( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - status_t *status) -{ - sp<AudioRecordThread> thread; - sp<MixerThread::RecordTrack> recordTrack; - sp<RecordHandle> recordHandle; - sp<Client> client; - wp<Client> wclient; - AudioStreamIn* input = 0; - int inFrameCount; - size_t inputBufferSize; - status_t lStatus; - - // check calling permissions - if (!recordingAllowed()) { - lStatus = PERMISSION_DENIED; - goto Exit; - } - - if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) { - LOGE("invalid stream type"); - lStatus = BAD_VALUE; - goto Exit; - } - - if (sampleRate > MAX_SAMPLE_RATE) { - LOGE("Sample rate out of range"); - lStatus = BAD_VALUE; - goto Exit; - } - - if (mAudioRecordThread == 0) { - LOGE("Audio record thread not started"); - lStatus = NO_INIT; - goto Exit; - } - - - // Check that audio input stream accepts requested audio parameters - inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount); - if (inputBufferSize == 0) { - lStatus = BAD_VALUE; - LOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d", sampleRate, format, channelCount); - goto Exit; - } - - // add client to list - { - Mutex::Autolock _l(mLock); - wclient = mClients.valueFor(pid); - if (wclient != NULL) { - client = wclient.promote(); - } else { - client = new Client(this, pid); - mClients.add(pid, client); - } - } - - // frameCount must be a multiple of input buffer size - inFrameCount = inputBufferSize/channelCount/sizeof(short); - frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount; - - // create new record track and pass to record thread - recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate, - format, channelCount, frameCount, flags); - if (recordTrack->getCblk() == NULL) { - recordTrack.clear(); - lStatus = NO_MEMORY; - goto Exit; - } - - // return to handle to client - recordHandle = new RecordHandle(recordTrack); - lStatus = NO_ERROR; - -Exit: - if (status) { - *status = lStatus; - } - return recordHandle; -} - -status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) { - if (mAudioRecordThread != 0) { - return mAudioRecordThread->start(recordTrack); - } - return NO_INIT; -} - -void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) { - if (mAudioRecordThread != 0) { - mAudioRecordThread->stop(recordTrack); - } -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack) - : BnAudioRecord(), - mRecordTrack(recordTrack) -{ -} - -AudioFlinger::RecordHandle::~RecordHandle() { - stop(); -} - -status_t AudioFlinger::RecordHandle::start() { - LOGV("RecordHandle::start()"); - return mRecordTrack->start(); -} - -void AudioFlinger::RecordHandle::stop() { - LOGV("RecordHandle::stop()"); - mRecordTrack->stop(); -} - -sp<IMemory> AudioFlinger::RecordHandle::getCblk() const { - return mRecordTrack->getCblk(); -} - -status_t AudioFlinger::RecordHandle::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - return BnAudioRecord::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) : - mAudioHardware(audioHardware), - mActive(false) -{ -} - -AudioFlinger::AudioRecordThread::~AudioRecordThread() -{ -} - -bool AudioFlinger::AudioRecordThread::threadLoop() -{ - LOGV("AudioRecordThread: start record loop"); - AudioBufferProvider::Buffer buffer; - int inBufferSize = 0; - int inFrameCount = 0; - AudioStreamIn* input = 0; - - mActive = 0; - - // start recording - while (!exitPending()) { - if (!mActive) { - mLock.lock(); - if (!mActive && !exitPending()) { - LOGV("AudioRecordThread: loop stopping"); - if (input) { - delete input; - input = 0; - } - mRecordTrack.clear(); - mStopped.signal(); - - mWaitWorkCV.wait(mLock); - - LOGV("AudioRecordThread: loop starting"); - if (mRecordTrack != 0) { - input = mAudioHardware->openInputStream(mRecordTrack->format(), - mRecordTrack->channelCount(), - mRecordTrack->sampleRate(), - &mStartStatus, - (AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags >> 16)); - if (input != 0) { - inBufferSize = input->bufferSize(); - inFrameCount = inBufferSize/input->frameSize(); - } - } else { - mStartStatus = NO_INIT; - } - if (mStartStatus !=NO_ERROR) { - LOGW("record start failed, status %d", mStartStatus); - mActive = false; - mRecordTrack.clear(); - } - mWaitWorkCV.signal(); - } - mLock.unlock(); - } else if (mRecordTrack != 0) { - - buffer.frameCount = inFrameCount; - if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) { - LOGV("AudioRecordThread read: %d frames", buffer.frameCount); - ssize_t bytesRead = input->read(buffer.raw, inBufferSize); - if (bytesRead < 0) { - LOGE("Error reading audio input"); - sleep(1); - } - mRecordTrack->releaseBuffer(&buffer); - mRecordTrack->overflow(); - } - - // client isn't retrieving buffers fast enough - else { - if (!mRecordTrack->setOverflow()) - LOGW("AudioRecordThread: buffer overflow"); - // Release the processor for a while before asking for a new buffer. - // This will give the application more chance to read from the buffer and - // clear the overflow. - usleep(5000); - } - } - } - - - if (input) { - delete input; - } - mRecordTrack.clear(); - - return false; -} - -status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack) -{ - LOGV("AudioRecordThread::start"); - AutoMutex lock(&mLock); - mActive = true; - // If starting the active track, just reset mActive in case a stop - // was pending and exit - if (recordTrack == mRecordTrack.get()) return NO_ERROR; - - if (mRecordTrack != 0) return -EBUSY; - - mRecordTrack = recordTrack; - - // signal thread to start - LOGV("Signal record thread"); - mWaitWorkCV.signal(); - mWaitWorkCV.wait(mLock); - LOGV("Record started, status %d", mStartStatus); - return mStartStatus; -} - -void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) { - LOGV("AudioRecordThread::stop"); - AutoMutex lock(&mLock); - if (mActive && (recordTrack == mRecordTrack.get())) { - mActive = false; - mStopped.wait(mLock); - } -} - -void AudioFlinger::AudioRecordThread::exit() -{ - LOGV("AudioRecordThread::exit"); - { - AutoMutex lock(&mLock); - requestExit(); - mWaitWorkCV.signal(); - } - requestExitAndWait(); -} - -status_t AudioFlinger::AudioRecordThread::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - pid_t pid = 0; - - if (mRecordTrack != 0 && mRecordTrack->mClient != 0) { - snprintf(buffer, SIZE, "Record client pid: %d\n", mRecordTrack->mClient->pid()); - result.append(buffer); - } else { - result.append("No record client\n"); - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - return BnAudioFlinger::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- -void AudioFlinger::instantiate() { - defaultServiceManager()->addService( - String16("media.audio_flinger"), new AudioFlinger()); -} - -}; // namespace android diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h deleted file mode 100644 index dfbb1e9..0000000 --- a/libs/audioflinger/AudioFlinger.h +++ /dev/null @@ -1,640 +0,0 @@ -/* //device/include/server/AudioFlinger/AudioFlinger.h -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef ANDROID_AUDIO_FLINGER_H -#define ANDROID_AUDIO_FLINGER_H - -#include <stdint.h> -#include <sys/types.h> - -#include <media/IAudioFlinger.h> -#include <media/IAudioFlingerClient.h> -#include <media/IAudioTrack.h> -#include <media/IAudioRecord.h> -#include <media/AudioTrack.h> - -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/threads.h> -#include <utils/MemoryDealer.h> -#include <utils/KeyedVector.h> -#include <utils/SortedVector.h> -#include <utils/Vector.h> - -#include <hardware_legacy/AudioHardwareInterface.h> - -#include "AudioBufferProvider.h" - -namespace android { - -class audio_track_cblk_t; -class AudioMixer; -class AudioBuffer; - - -// ---------------------------------------------------------------------------- - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - - -// ---------------------------------------------------------------------------- - -static const nsecs_t kStandbyTimeInNsecs = seconds(3); - -class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient -{ -public: - static void instantiate(); - - virtual status_t dump(int fd, const Vector<String16>& args); - - // IAudioFlinger interface - virtual sp<IAudioTrack> createTrack( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp<IMemory>& sharedBuffer, - status_t *status); - - virtual uint32_t sampleRate(int output) const; - virtual int channelCount(int output) const; - virtual int format(int output) const; - virtual size_t frameCount(int output) const; - virtual uint32_t latency(int output) const; - - virtual status_t setMasterVolume(float value); - virtual status_t setMasterMute(bool muted); - - virtual float masterVolume() const; - virtual bool masterMute() const; - - virtual status_t setStreamVolume(int stream, float value); - virtual status_t setStreamMute(int stream, bool muted); - - virtual float streamVolume(int stream) const; - virtual bool streamMute(int stream) const; - - virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask); - virtual uint32_t getRouting(int mode) const; - - virtual status_t setMode(int mode); - virtual int getMode() const; - - virtual status_t setMicMute(bool state); - virtual bool getMicMute() const; - - virtual bool isMusicActive() const; - - virtual bool isA2dpEnabled() const; - - virtual status_t setParameter(const char* key, const char* value); - - virtual void registerClient(const sp<IAudioFlingerClient>& client); - - virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); - - virtual void wakeUp(); - - // IBinder::DeathRecipient - virtual void binderDied(const wp<IBinder>& who); - - enum hardware_call_state { - AUDIO_HW_IDLE = 0, - AUDIO_HW_INIT, - AUDIO_HW_OUTPUT_OPEN, - AUDIO_HW_OUTPUT_CLOSE, - AUDIO_HW_INPUT_OPEN, - AUDIO_HW_INPUT_CLOSE, - AUDIO_HW_STANDBY, - AUDIO_HW_SET_MASTER_VOLUME, - AUDIO_HW_GET_ROUTING, - AUDIO_HW_SET_ROUTING, - AUDIO_HW_GET_MODE, - AUDIO_HW_SET_MODE, - AUDIO_HW_GET_MIC_MUTE, - AUDIO_HW_SET_MIC_MUTE, - AUDIO_SET_VOICE_VOLUME, - AUDIO_SET_PARAMETER, - }; - - // record interface - virtual sp<IAudioRecord> openRecord( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - status_t *status); - - virtual status_t onTransact( - uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags); - -private: - AudioFlinger(); - virtual ~AudioFlinger(); - - void setOutput(int outputType); - void doSetOutput(int outputType); - -#ifdef WITH_A2DP - void setA2dpEnabled(bool enable); -#endif - static bool streamForcedToSpeaker(int streamType); - - // Management of forced route to speaker for certain track types. - enum force_speaker_command { - ACTIVE_TRACK_ADDED = 0, - ACTIVE_TRACK_REMOVED, - CHECK_ROUTE_RESTORE_TIME, - FORCE_ROUTE_RESTORE - }; - void handleForcedSpeakerRoute(int command); - - // Internal dump utilites. - status_t dumpPermissionDenial(int fd, const Vector<String16>& args); - status_t dumpClients(int fd, const Vector<String16>& args); - status_t dumpInternals(int fd, const Vector<String16>& args); - - // --- Client --- - class Client : public RefBase { - public: - Client(const sp<AudioFlinger>& audioFlinger, pid_t pid); - virtual ~Client(); - const sp<MemoryDealer>& heap() const; - pid_t pid() const { return mPid; } - private: - Client(const Client&); - Client& operator = (const Client&); - sp<AudioFlinger> mAudioFlinger; - sp<MemoryDealer> mMemoryDealer; - pid_t mPid; - }; - - - class TrackHandle; - class RecordHandle; - class AudioRecordThread; - - - // --- MixerThread --- - class MixerThread : public Thread { - public: - - // --- Track --- - - // base for record and playback - class TrackBase : public AudioBufferProvider, public RefBase { - - public: - enum track_state { - IDLE, - TERMINATED, - STOPPED, - RESUMING, - ACTIVE, - PAUSING, - PAUSED - }; - - enum track_flags { - STEPSERVER_FAILED = 0x01, // StepServer could not acquire cblk->lock mutex - SYSTEM_FLAGS_MASK = 0x0000ffffUL, - - AUDIO_IN_AGC_ENABLE = AudioSystem::AGC_ENABLE << 16, - AUDIO_IN_NS_ENABLE = AudioSystem::NS_ENABLE << 16, - AUDIO_IN_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE << 16 - }; - - TrackBase(const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp<IMemory>& sharedBuffer); - ~TrackBase(); - - virtual status_t start() = 0; - virtual void stop() = 0; - sp<IMemory> getCblk() const; - - protected: - friend class MixerThread; - friend class RecordHandle; - friend class AudioRecordThread; - - TrackBase(const TrackBase&); - TrackBase& operator = (const TrackBase&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0; - virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); - - audio_track_cblk_t* cblk() const { - return mCblk; - } - - int type() const { - return mStreamType; - } - - int format() const { - return mFormat; - } - - int channelCount() const ; - - int sampleRate() const; - - void* getBuffer(uint32_t offset, uint32_t frames) const; - - int name() const { - return mName; - } - - bool isStopped() const { - return mState == STOPPED; - } - - bool isTerminated() const { - return mState == TERMINATED; - } - - bool step(); - void reset(); - - sp<MixerThread> mMixerThread; - sp<Client> mClient; - sp<IMemory> mCblkMemory; - audio_track_cblk_t* mCblk; - int mStreamType; - void* mBuffer; - void* mBufferEnd; - uint32_t mFrameCount; - int mName; - // we don't really need a lock for these - int mState; - int mClientTid; - uint8_t mFormat; - uint32_t mFlags; - }; - - // playback track - class Track : public TrackBase { - public: - Track( const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer); - ~Track(); - - void dump(char* buffer, size_t size); - virtual status_t start(); - virtual void stop(); - void pause(); - - void flush(); - void destroy(); - void mute(bool); - void setVolume(float left, float right); - - protected: - friend class MixerThread; - friend class AudioFlinger; - friend class AudioFlinger::TrackHandle; - - Track(const Track&); - Track& operator = (const Track&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); - - bool isMuted() const { - return (mMute || mMixerThread->mStreamTypes[mStreamType].mute); - } - - bool isPausing() const { - return mState == PAUSING; - } - - bool isPaused() const { - return mState == PAUSED; - } - - bool isReady() const; - - void setPaused() { mState = PAUSED; } - void reset(); - - // we don't really need a lock for these - float mVolume[2]; - volatile bool mMute; - // FILLED state is used for suppressing volume ramp at begin of playing - enum {FS_FILLING, FS_FILLED, FS_ACTIVE}; - mutable uint8_t mFillingUpStatus; - int8_t mRetryCount; - sp<IMemory> mSharedBuffer; - bool mResetDone; - }; // end of Track - - // record track - class RecordTrack : public TrackBase { - public: - RecordTrack(const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags); - ~RecordTrack(); - - virtual status_t start(); - virtual void stop(); - - bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; } - bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; } - - private: - friend class AudioFlinger; - friend class AudioFlinger::RecordHandle; - friend class AudioFlinger::AudioRecordThread; - friend class MixerThread; - - RecordTrack(const Track&); - RecordTrack& operator = (const Track&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); - - bool mOverflow; - }; - - // playback track - class OutputTrack : public Track { - public: - - class Buffer: public AudioBufferProvider::Buffer { - public: - int16_t *mBuffer; - }; - - OutputTrack( const sp<MixerThread>& mixerThread, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount); - ~OutputTrack(); - - virtual status_t start(); - virtual void stop(); - void write(int16_t* data, uint32_t frames); - bool bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; } - - private: - - status_t obtainBuffer(AudioBufferProvider::Buffer* buffer); - void clearBufferQueue(); - - sp<MixerThread> mOutputMixerThread; - Vector < Buffer* > mBufferQueue; - AudioBufferProvider::Buffer mOutBuffer; - uint32_t mFramesWritten; - - }; // end of OutputTrack - - MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType); - virtual ~MixerThread(); - - virtual status_t dump(int fd, const Vector<String16>& args); - - // Thread virtuals - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void onFirstRef(); - - virtual uint32_t sampleRate() const; - virtual int channelCount() const; - virtual int format() const; - virtual size_t frameCount() const; - virtual uint32_t latency() const; - - virtual status_t setMasterVolume(float value); - virtual status_t setMasterMute(bool muted); - - virtual float masterVolume() const; - virtual bool masterMute() const; - - virtual status_t setStreamVolume(int stream, float value); - virtual status_t setStreamMute(int stream, bool muted); - - virtual float streamVolume(int stream) const; - virtual bool streamMute(int stream) const; - - bool isMusicActive() const; - - - sp<Track> createTrack( - const sp<AudioFlinger::Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer, - status_t *status); - - void wakeUp() { mWaitWorkCV.broadcast(); } - - void getTracks(SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks); - void putTracks(SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks); - void setOuputTrack(OutputTrack *track) { mOutputTrack = track; } - - struct stream_type_t { - stream_type_t() - : volume(1.0f), - mute(false) - { - } - float volume; - bool mute; - }; - - private: - - - friend class AudioFlinger; - friend class Track; - friend class TrackBase; - friend class RecordTrack; - - MixerThread(const Client&); - MixerThread& operator = (const MixerThread&); - - status_t addTrack(const sp<Track>& track); - void removeTrack(wp<Track> track, int name); - void remove_track_l(wp<Track> track, int name); - void destroyTrack(const sp<Track>& track); - int getTrackName(); - void deleteTrackName(int name); - void addActiveTrack(const wp<Track>& t); - void removeActiveTrack(const wp<Track>& t); - size_t getOutputFrameCount(); - - status_t dumpInternals(int fd, const Vector<String16>& args); - status_t dumpTracks(int fd, const Vector<String16>& args); - - sp<AudioFlinger> mAudioFlinger; - mutable Mutex mLock; - mutable Condition mWaitWorkCV; - SortedVector< wp<Track> > mActiveTracks; - SortedVector< sp<Track> > mTracks; - stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES]; - AudioMixer* mAudioMixer; - AudioStreamOut* mOutput; - int mOutputType; - uint32_t mSampleRate; - size_t mFrameCount; - int mChannelCount; - int mFormat; - int16_t* mMixBuffer; - float mMasterVolume; - bool mMasterMute; - nsecs_t mLastWriteTime; - int mNumWrites; - int mNumDelayedWrites; - bool mStandby; - bool mInWrite; - sp <OutputTrack> mOutputTrack; - }; - - - friend class AudioBuffer; - - class TrackHandle : public android::BnAudioTrack { - public: - TrackHandle(const sp<MixerThread::Track>& track); - virtual ~TrackHandle(); - virtual status_t start(); - virtual void stop(); - virtual void flush(); - virtual void mute(bool); - virtual void pause(); - virtual void setVolume(float left, float right); - virtual sp<IMemory> getCblk() const; - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - private: - sp<MixerThread::Track> mTrack; - }; - - friend class Client; - friend class MixerThread::Track; - - - void removeClient(pid_t pid); - - - - class RecordHandle : public android::BnAudioRecord { - public: - RecordHandle(const sp<MixerThread::RecordTrack>& recordTrack); - virtual ~RecordHandle(); - virtual status_t start(); - virtual void stop(); - virtual sp<IMemory> getCblk() const; - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - private: - sp<MixerThread::RecordTrack> mRecordTrack; - }; - - // record thread - class AudioRecordThread : public Thread - { - public: - AudioRecordThread(AudioHardwareInterface* audioHardware); - virtual ~AudioRecordThread(); - virtual bool threadLoop(); - virtual status_t readyToRun() { return NO_ERROR; } - virtual void onFirstRef() {} - - status_t start(MixerThread::RecordTrack* recordTrack); - void stop(MixerThread::RecordTrack* recordTrack); - void exit(); - status_t dump(int fd, const Vector<String16>& args); - - private: - AudioRecordThread(); - AudioHardwareInterface *mAudioHardware; - sp<MixerThread::RecordTrack> mRecordTrack; - Mutex mLock; - Condition mWaitWorkCV; - Condition mStopped; - volatile bool mActive; - status_t mStartStatus; - }; - - friend class AudioRecordThread; - friend class MixerThread; - - status_t startRecord(MixerThread::RecordTrack* recordTrack); - void stopRecord(MixerThread::RecordTrack* recordTrack); - - void handleOutputSwitch(); - - mutable Mutex mHardwareLock; - mutable Mutex mLock; - DefaultKeyedVector< pid_t, wp<Client> > mClients; - - sp<MixerThread> mA2dpMixerThread; - sp<MixerThread> mHardwareMixerThread; - AudioHardwareInterface* mAudioHardware; - AudioHardwareInterface* mA2dpAudioInterface; - sp<AudioRecordThread> mAudioRecordThread; - bool mA2dpEnabled; - bool mA2dpEnabledReq; - mutable int mHardwareStatus; - SortedVector< wp<IBinder> > mNotificationClients; - int mForcedSpeakerCount; - uint32_t mSavedRoute; - uint32_t mForcedRoute; - nsecs_t mRouteRestoreTime; - bool mMusicMuteSaved; -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_AUDIO_FLINGER_H diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp deleted file mode 100644 index 62beada..0000000 --- a/libs/audioflinger/AudioHardwareGeneric.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include <stdint.h> -#include <sys/types.h> - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <sched.h> -#include <fcntl.h> -#include <sys/ioctl.h> - -#define LOG_TAG "AudioHardware" -#include <utils/Log.h> -#include <utils/String8.h> - -#include "AudioHardwareGeneric.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -static char const * const kAudioDeviceName = "/dev/eac"; - -// ---------------------------------------------------------------------------- - -AudioHardwareGeneric::AudioHardwareGeneric() - : mOutput(0), mInput(0), mFd(-1), mMicMute(false) -{ - mFd = ::open(kAudioDeviceName, O_RDWR); -} - -AudioHardwareGeneric::~AudioHardwareGeneric() -{ - if (mFd >= 0) ::close(mFd); - delete mOutput; - delete mInput; -} - -status_t AudioHardwareGeneric::initCheck() -{ - if (mFd >= 0) { - if (::access(kAudioDeviceName, O_RDWR) == NO_ERROR) - return NO_ERROR; - } - return NO_INIT; -} - -AudioStreamOut* AudioHardwareGeneric::openOutputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) -{ - AutoMutex lock(mLock); - - // only one output stream allowed - if (mOutput) { - if (status) { - *status = INVALID_OPERATION; - } - return 0; - } - - // create new output stream - AudioStreamOutGeneric* out = new AudioStreamOutGeneric(); - status_t lStatus = out->set(this, mFd, format, channelCount, sampleRate); - if (status) { - *status = lStatus; - } - if (lStatus == NO_ERROR) { - mOutput = out; - } else { - delete out; - } - return mOutput; -} - -void AudioHardwareGeneric::closeOutputStream(AudioStreamOutGeneric* out) { - if (out == mOutput) mOutput = 0; -} - -AudioStreamIn* AudioHardwareGeneric::openInputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status, - AudioSystem::audio_in_acoustics acoustics) -{ - AutoMutex lock(mLock); - - // only one input stream allowed - if (mInput) { - if (status) { - *status = INVALID_OPERATION; - } - return 0; - } - - // create new output stream - AudioStreamInGeneric* in = new AudioStreamInGeneric(); - status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate, acoustics); - if (status) { - *status = lStatus; - } - if (lStatus == NO_ERROR) { - mInput = in; - } else { - delete in; - } - return mInput; -} - -void AudioHardwareGeneric::closeInputStream(AudioStreamInGeneric* in) { - if (in == mInput) mInput = 0; -} - -status_t AudioHardwareGeneric::setVoiceVolume(float v) -{ - // Implement: set voice volume - return NO_ERROR; -} - -status_t AudioHardwareGeneric::setMasterVolume(float v) -{ - // Implement: set master volume - // return error - software mixer will handle it - return INVALID_OPERATION; -} - -status_t AudioHardwareGeneric::setMicMute(bool state) -{ - mMicMute = state; - return NO_ERROR; -} - -status_t AudioHardwareGeneric::getMicMute(bool* state) -{ - *state = mMicMute; - return NO_ERROR; -} - -status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - result.append("AudioHardwareGeneric::dumpInternals\n"); - snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false"); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args) -{ - dumpInternals(fd, args); - if (mInput) { - mInput->dump(fd, args); - } - if (mOutput) { - mOutput->dump(fd, args); - } - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -status_t AudioStreamOutGeneric::set( - AudioHardwareGeneric *hw, - int fd, - int format, - int channels, - uint32_t rate) -{ - // fix up defaults - if (format == 0) format = AudioSystem::PCM_16_BIT; - if (channels == 0) channels = channelCount(); - if (rate == 0) rate = sampleRate(); - - // check values - if ((format != AudioSystem::PCM_16_BIT) || - (channels != channelCount()) || - (rate != sampleRate())) - return BAD_VALUE; - - mAudioHardware = hw; - mFd = fd; - return NO_ERROR; -} - -AudioStreamOutGeneric::~AudioStreamOutGeneric() -{ - if (mAudioHardware) - mAudioHardware->closeOutputStream(this); -} - -ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes) -{ - Mutex::Autolock _l(mLock); - return ssize_t(::write(mFd, buffer, bytes)); -} - -status_t AudioStreamOutGeneric::standby() -{ - // Implement: audio hardware to standby mode - return NO_ERROR; -} - -status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n"); - result.append(buffer); - snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); - result.append(buffer); - snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); - result.append(buffer); - snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); - result.append(buffer); - snprintf(buffer, SIZE, "\tformat: %d\n", format()); - result.append(buffer); - snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware); - result.append(buffer); - snprintf(buffer, SIZE, "\tmFd: %d\n", mFd); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -// record functions -status_t AudioStreamInGeneric::set( - AudioHardwareGeneric *hw, - int fd, - int format, - int channels, - uint32_t rate, - AudioSystem::audio_in_acoustics acoustics) -{ - // FIXME: remove logging - LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, format, channels, rate); - // check values - if ((format != AudioSystem::PCM_16_BIT) || - (channels != channelCount()) || - (rate != sampleRate())) { - LOGE("Error opening input channel"); - return BAD_VALUE; - } - - mAudioHardware = hw; - mFd = fd; - return NO_ERROR; -} - -AudioStreamInGeneric::~AudioStreamInGeneric() -{ - // FIXME: remove logging - LOGD("AudioStreamInGeneric destructor"); - if (mAudioHardware) - mAudioHardware->closeInputStream(this); -} - -ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes) -{ - // FIXME: remove logging - LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, bytes, mFd); - AutoMutex lock(mLock); - if (mFd < 0) { - LOGE("Attempt to read from unopened device"); - return NO_INIT; - } - return ::read(mFd, buffer, bytes); -} - -status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n"); - result.append(buffer); - snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); - result.append(buffer); - snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); - result.append(buffer); - snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); - result.append(buffer); - snprintf(buffer, SIZE, "\tformat: %d\n", format()); - result.append(buffer); - snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware); - result.append(buffer); - snprintf(buffer, SIZE, "\tmFd: %d\n", mFd); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h deleted file mode 100644 index 1d58389..0000000 --- a/libs/audioflinger/AudioHardwareGeneric.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef ANDROID_AUDIO_HARDWARE_GENERIC_H -#define ANDROID_AUDIO_HARDWARE_GENERIC_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/threads.h> - -#include <hardware_legacy/AudioHardwareBase.h> - -namespace android { - -// ---------------------------------------------------------------------------- - -class AudioHardwareGeneric; - -class AudioStreamOutGeneric : public AudioStreamOut { -public: - AudioStreamOutGeneric() : mAudioHardware(0), mFd(-1) {} - virtual ~AudioStreamOutGeneric(); - - virtual status_t set( - AudioHardwareGeneric *hw, - int mFd, - int format, - int channelCount, - uint32_t sampleRate); - - virtual uint32_t sampleRate() const { return 44100; } - virtual size_t bufferSize() const { return 4096; } - virtual int channelCount() const { return 2; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return 0; } - virtual status_t setVolume(float volume) { return INVALID_OPERATION; } - virtual ssize_t write(const void* buffer, size_t bytes); - virtual status_t standby(); - virtual status_t dump(int fd, const Vector<String16>& args); - -private: - AudioHardwareGeneric *mAudioHardware; - Mutex mLock; - int mFd; -}; - -class AudioStreamInGeneric : public AudioStreamIn { -public: - AudioStreamInGeneric() : mAudioHardware(0), mFd(-1) {} - virtual ~AudioStreamInGeneric(); - - virtual status_t set( - AudioHardwareGeneric *hw, - int mFd, - int format, - int channelCount, - uint32_t sampleRate, - AudioSystem::audio_in_acoustics acoustics); - - uint32_t sampleRate() const { return 8000; } - virtual size_t bufferSize() const { return 320; } - virtual int channelCount() const { return 1; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual status_t setGain(float gain) { return INVALID_OPERATION; } - virtual ssize_t read(void* buffer, ssize_t bytes); - virtual status_t dump(int fd, const Vector<String16>& args); - virtual status_t standby() { return NO_ERROR; } - -private: - AudioHardwareGeneric *mAudioHardware; - Mutex mLock; - int mFd; -}; - - -class AudioHardwareGeneric : public AudioHardwareBase -{ -public: - AudioHardwareGeneric(); - virtual ~AudioHardwareGeneric(); - virtual status_t initCheck(); - virtual status_t setVoiceVolume(float volume); - virtual status_t setMasterVolume(float volume); - - // mic mute - virtual status_t setMicMute(bool state); - virtual status_t getMicMute(bool* state); - - virtual status_t setParameter(const char* key, const char* value) - { return NO_ERROR; } - - // create I/O streams - virtual AudioStreamOut* openOutputStream( - int format=0, - int channelCount=0, - uint32_t sampleRate=0, - status_t *status=0); - - virtual AudioStreamIn* openInputStream( - int format, - int channelCount, - uint32_t sampleRate, - status_t *status, - AudioSystem::audio_in_acoustics acoustics); - - void closeOutputStream(AudioStreamOutGeneric* out); - void closeInputStream(AudioStreamInGeneric* in); -protected: - virtual status_t doRouting() { return NO_ERROR; } - virtual status_t dump(int fd, const Vector<String16>& args); - -private: - status_t dumpInternals(int fd, const Vector<String16>& args); - - Mutex mLock; - AudioStreamOutGeneric *mOutput; - AudioStreamInGeneric *mInput; - int mFd; - bool mMicMute; -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_AUDIO_HARDWARE_GENERIC_H diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp deleted file mode 100644 index ac76a19..0000000 --- a/libs/audioflinger/AudioHardwareInterface.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include <cutils/properties.h> -#include <string.h> -#include <unistd.h> - -#define LOG_TAG "AudioHardwareInterface" -#include <utils/Log.h> -#include <utils/String8.h> - -#include "AudioHardwareStub.h" -#include "AudioHardwareGeneric.h" - -//#define DUMP_FLINGER_OUT // if defined allows recording samples in a file -#ifdef DUMP_FLINGER_OUT -#include "AudioDumpInterface.h" -#endif - - -// change to 1 to log routing calls -#define LOG_ROUTING_CALLS 0 - -namespace android { - -#if LOG_ROUTING_CALLS -static const char* routingModeStrings[] = -{ - "OUT OF RANGE", - "INVALID", - "CURRENT", - "NORMAL", - "RINGTONE", - "IN_CALL" -}; - -static const char* routeStrings[] = -{ - "EARPIECE ", - "SPEAKER ", - "BLUETOOTH ", - "HEADSET " - "BLUETOOTH_A2DP " -}; -static const char* routeNone = "NONE"; - -static const char* displayMode(int mode) -{ - if ((mode < -2) || (mode > 2)) - return routingModeStrings[0]; - return routingModeStrings[mode+3]; -} - -static const char* displayRoutes(uint32_t routes) -{ - static char routeStr[80]; - if (routes == 0) - return routeNone; - routeStr[0] = 0; - int bitMask = 1; - for (int i = 0; i < 4; ++i, bitMask <<= 1) { - if (routes & bitMask) { - strcat(routeStr, routeStrings[i]); - } - } - routeStr[strlen(routeStr)-1] = 0; - return routeStr; -} -#endif - -// ---------------------------------------------------------------------------- - -AudioHardwareInterface* AudioHardwareInterface::create() -{ - /* - * FIXME: This code needs to instantiate the correct audio device - * interface. For now - we use compile-time switches. - */ - AudioHardwareInterface* hw = 0; - char value[PROPERTY_VALUE_MAX]; - -#ifdef GENERIC_AUDIO - hw = new AudioHardwareGeneric(); -#else - // if running in emulation - use the emulator driver - if (property_get("ro.kernel.qemu", value, 0)) { - LOGD("Running in emulation - using generic audio driver"); - hw = new AudioHardwareGeneric(); - } - else { - LOGV("Creating Vendor Specific AudioHardware"); - hw = createAudioHardware(); - } -#endif - if (hw->initCheck() != NO_ERROR) { - LOGW("Using stubbed audio hardware. No sound will be produced."); - delete hw; - hw = new AudioHardwareStub(); - } - -#ifdef DUMP_FLINGER_OUT - // This code adds a record of buffers in a file to write calls made by AudioFlinger. - // It replaces the current AudioHardwareInterface object by an intermediate one which - // will record buffers in a file (after sending them to hardware) for testing purpose. - // This feature is enabled by defining symbol DUMP_FLINGER_OUT. - // The output file is FLINGER_DUMP_NAME. Pause are not recorded in the file. - - hw = new AudioDumpInterface(hw); // replace interface -#endif - return hw; -} - -AudioStreamOut::~AudioStreamOut() -{ -} - -AudioStreamIn::~AudioStreamIn() {} - -AudioHardwareBase::AudioHardwareBase() -{ - // force a routing update on initialization - memset(&mRoutes, 0, sizeof(mRoutes)); - mMode = 0; -} - -// generics for audio routing - the real work is done in doRouting -status_t AudioHardwareBase::setRouting(int mode, uint32_t routes) -{ -#if LOG_ROUTING_CALLS - LOGD("setRouting: mode=%s, routes=[%s]", displayMode(mode), displayRoutes(routes)); -#endif - if (mode == AudioSystem::MODE_CURRENT) - mode = mMode; - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) - return BAD_VALUE; - uint32_t old = mRoutes[mode]; - mRoutes[mode] = routes; - if ((mode != mMode) || (old == routes)) - return NO_ERROR; -#if LOG_ROUTING_CALLS - const char* oldRouteStr = strdup(displayRoutes(old)); - LOGD("doRouting: mode=%s, old route=[%s], new route=[%s]", - displayMode(mode), oldRouteStr, displayRoutes(routes)); - delete oldRouteStr; -#endif - return doRouting(); -} - -status_t AudioHardwareBase::getRouting(int mode, uint32_t* routes) -{ - if (mode == AudioSystem::MODE_CURRENT) - mode = mMode; - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) - return BAD_VALUE; - *routes = mRoutes[mode]; -#if LOG_ROUTING_CALLS - LOGD("getRouting: mode=%s, routes=[%s]", - displayMode(mode), displayRoutes(*routes)); -#endif - return NO_ERROR; -} - -status_t AudioHardwareBase::setMode(int mode) -{ -#if LOG_ROUTING_CALLS - LOGD("setMode(%s)", displayMode(mode)); -#endif - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) - return BAD_VALUE; - if (mMode == mode) - return NO_ERROR; -#if LOG_ROUTING_CALLS - LOGD("doRouting: old mode=%s, new mode=%s route=[%s]", - displayMode(mMode), displayMode(mode), displayRoutes(mRoutes[mode])); -#endif - mMode = mode; - return doRouting(); -} - -status_t AudioHardwareBase::getMode(int* mode) -{ - // Implement: set audio routing - *mode = mMode; - return NO_ERROR; -} - -status_t AudioHardwareBase::setParameter(const char* key, const char* value) -{ - // default implementation is to ignore - return NO_ERROR; -} - - -// default implementation -size_t AudioHardwareBase::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) -{ - if (sampleRate != 8000) { - LOGW("getInputBufferSize bad sampling rate: %d", sampleRate); - return 0; - } - if (format != AudioSystem::PCM_16_BIT) { - LOGW("getInputBufferSize bad format: %d", format); - return 0; - } - if (channelCount != 1) { - LOGW("getInputBufferSize bad channel count: %d", channelCount); - return 0; - } - - return 320; -} - -status_t AudioHardwareBase::dumpState(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioHardwareBase::dumpState\n"); - result.append(buffer); - snprintf(buffer, SIZE, "\tmMode: %d\n", mMode); - result.append(buffer); - for (int i = 0, n = AudioSystem::NUM_MODES; i < n; ++i) { - snprintf(buffer, SIZE, "\tmRoutes[%d]: %d\n", i, mRoutes[i]); - result.append(buffer); - } - ::write(fd, result.string(), result.size()); - dump(fd, args); // Dump the state of the concrete child. - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp deleted file mode 100644 index b13cb1c..0000000 --- a/libs/audioflinger/AudioHardwareStub.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* //device/servers/AudioFlinger/AudioHardwareStub.cpp -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include <stdint.h> -#include <sys/types.h> - -#include <stdlib.h> -#include <unistd.h> -#include <utils/String8.h> - -#include "AudioHardwareStub.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -AudioHardwareStub::AudioHardwareStub() : mMicMute(false) -{ -} - -AudioHardwareStub::~AudioHardwareStub() -{ -} - -status_t AudioHardwareStub::initCheck() -{ - return NO_ERROR; -} - -AudioStreamOut* AudioHardwareStub::openOutputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) -{ - AudioStreamOutStub* out = new AudioStreamOutStub(); - status_t lStatus = out->set(format, channelCount, sampleRate); - if (status) { - *status = lStatus; - } - if (lStatus == NO_ERROR) - return out; - delete out; - return 0; -} - -AudioStreamIn* AudioHardwareStub::openInputStream( - int format, int channelCount, uint32_t sampleRate, - status_t *status, AudioSystem::audio_in_acoustics acoustics) -{ - AudioStreamInStub* in = new AudioStreamInStub(); - status_t lStatus = in->set(format, channelCount, sampleRate, acoustics); - if (status) { - *status = lStatus; - } - if (lStatus == NO_ERROR) - return in; - delete in; - return 0; -} - -status_t AudioHardwareStub::setVoiceVolume(float volume) -{ - return NO_ERROR; -} - -status_t AudioHardwareStub::setMasterVolume(float volume) -{ - return NO_ERROR; -} - -status_t AudioHardwareStub::dumpInternals(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - result.append("AudioHardwareStub::dumpInternals\n"); - snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false"); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioHardwareStub::dump(int fd, const Vector<String16>& args) -{ - dumpInternals(fd, args); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -status_t AudioStreamOutStub::set(int format, int channels, uint32_t rate) -{ - // fix up defaults - if (format == 0) format = AudioSystem::PCM_16_BIT; - if (channels == 0) channels = channelCount(); - if (rate == 0) rate = sampleRate(); - - if ((format == AudioSystem::PCM_16_BIT) && - (channels == channelCount()) && - (rate == sampleRate())) - return NO_ERROR; - return BAD_VALUE; -} - -ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes) -{ - // fake timing for audio output - usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate()); - return bytes; -} - -status_t AudioStreamOutStub::standby() -{ - return NO_ERROR; -} - -status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioStreamOutStub::dump\n"); - snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); - snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); - snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); - snprintf(buffer, SIZE, "\tformat: %d\n", format()); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -status_t AudioStreamInStub::set(int format, int channels, uint32_t rate, - AudioSystem::audio_in_acoustics acoustics) -{ - if ((format == AudioSystem::PCM_16_BIT) && - (channels == channelCount()) && - (rate == sampleRate())) - return NO_ERROR; - return BAD_VALUE; -} - -ssize_t AudioStreamInStub::read(void* buffer, ssize_t bytes) -{ - // fake timing for audio input - usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate()); - memset(buffer, 0, bytes); - return bytes; -} - -status_t AudioStreamInStub::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioStreamInStub::dump\n"); - result.append(buffer); - snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); - result.append(buffer); - snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); - result.append(buffer); - snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); - result.append(buffer); - snprintf(buffer, SIZE, "\tformat: %d\n", format()); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h deleted file mode 100644 index d406424..0000000 --- a/libs/audioflinger/AudioHardwareStub.h +++ /dev/null @@ -1,100 +0,0 @@ -/* //device/servers/AudioFlinger/AudioHardwareStub.h -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef ANDROID_AUDIO_HARDWARE_STUB_H -#define ANDROID_AUDIO_HARDWARE_STUB_H - -#include <stdint.h> -#include <sys/types.h> - -#include <hardware_legacy/AudioHardwareBase.h> - -namespace android { - -// ---------------------------------------------------------------------------- - -class AudioStreamOutStub : public AudioStreamOut { -public: - virtual status_t set(int format, int channelCount, uint32_t sampleRate); - virtual uint32_t sampleRate() const { return 44100; } - virtual size_t bufferSize() const { return 4096; } - virtual int channelCount() const { return 2; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return 0; } - virtual status_t setVolume(float volume) { return NO_ERROR; } - virtual ssize_t write(const void* buffer, size_t bytes); - virtual status_t standby(); - virtual status_t dump(int fd, const Vector<String16>& args); -}; - -class AudioStreamInStub : public AudioStreamIn { -public: - virtual status_t set(int format, int channelCount, uint32_t sampleRate, AudioSystem::audio_in_acoustics acoustics); - virtual uint32_t sampleRate() const { return 8000; } - virtual size_t bufferSize() const { return 320; } - virtual int channelCount() const { return 1; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual status_t setGain(float gain) { return NO_ERROR; } - virtual ssize_t read(void* buffer, ssize_t bytes); - virtual status_t dump(int fd, const Vector<String16>& args); - virtual status_t standby() { return NO_ERROR; } -}; - -class AudioHardwareStub : public AudioHardwareBase -{ -public: - AudioHardwareStub(); - virtual ~AudioHardwareStub(); - virtual status_t initCheck(); - virtual status_t setVoiceVolume(float volume); - virtual status_t setMasterVolume(float volume); - - // mic mute - virtual status_t setMicMute(bool state) { mMicMute = state; return NO_ERROR; } - virtual status_t getMicMute(bool* state) { *state = mMicMute ; return NO_ERROR; } - - virtual status_t setParameter(const char* key, const char* value) - { return NO_ERROR; } - - // create I/O streams - virtual AudioStreamOut* openOutputStream( - int format=0, - int channelCount=0, - uint32_t sampleRate=0, - status_t *status=0); - - virtual AudioStreamIn* openInputStream( - int format, - int channelCount, - uint32_t sampleRate, - status_t *status, - AudioSystem::audio_in_acoustics acoustics); - -protected: - virtual status_t doRouting() { return NO_ERROR; } - virtual status_t dump(int fd, const Vector<String16>& args); - - bool mMicMute; -private: - status_t dumpInternals(int fd, const Vector<String16>& args); -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_AUDIO_HARDWARE_STUB_H diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp deleted file mode 100644 index b03467f..0000000 --- a/libs/audioflinger/AudioMixer.cpp +++ /dev/null @@ -1,913 +0,0 @@ -/* //device/include/server/AudioFlinger/AudioMixer.cpp -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_TAG "AudioMixer" - -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include "AudioMixer.h" - -namespace android { -// ---------------------------------------------------------------------------- - -static inline int16_t clamp16(int32_t sample) -{ - if ((sample>>15) ^ (sample>>31)) - sample = 0x7FFF ^ (sample>>31); - return sample; -} - -// ---------------------------------------------------------------------------- - -AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate) - : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate) -{ - mState.enabledTracks= 0; - mState.needsChanged = 0; - mState.frameCount = frameCount; - mState.outputTemp = 0; - mState.resampleTemp = 0; - mState.hook = process__nop; - track_t* t = mState.tracks; - for (int i=0 ; i<32 ; i++) { - t->needs = 0; - t->volume[0] = UNITY_GAIN; - t->volume[1] = UNITY_GAIN; - t->volumeInc[0] = 0; - t->volumeInc[1] = 0; - t->channelCount = 2; - t->enabled = 0; - t->format = 16; - t->buffer.raw = 0; - t->bufferProvider = 0; - t->hook = 0; - t->resampler = 0; - t->sampleRate = mSampleRate; - t->in = 0; - t++; - } -} - - AudioMixer::~AudioMixer() - { - track_t* t = mState.tracks; - for (int i=0 ; i<32 ; i++) { - delete t->resampler; - t++; - } - delete [] mState.outputTemp; - delete [] mState.resampleTemp; - } - - int AudioMixer::getTrackName() - { - uint32_t names = mTrackNames; - uint32_t mask = 1; - int n = 0; - while (names & mask) { - mask <<= 1; - n++; - } - if (mask) { - LOGV("add track (%d)", n); - mTrackNames |= mask; - return TRACK0 + n; - } - return -1; - } - - void AudioMixer::invalidateState(uint32_t mask) - { - if (mask) { - mState.needsChanged |= mask; - mState.hook = process__validate; - } - } - - void AudioMixer::deleteTrackName(int name) - { - name -= TRACK0; - if (uint32_t(name) < MAX_NUM_TRACKS) { - LOGV("deleteTrackName(%d)", name); - track_t& track(mState.tracks[ name ]); - if (track.enabled != 0) { - track.enabled = 0; - invalidateState(1<<name); - } - if (track.resampler) { - // delete the resampler - delete track.resampler; - track.resampler = 0; - track.sampleRate = mSampleRate; - invalidateState(1<<name); - } - track.volumeInc[0] = 0; - track.volumeInc[1] = 0; - mTrackNames &= ~(1<<name); - } - } - -status_t AudioMixer::enable(int name) -{ - switch (name) { - case MIXING: { - if (mState.tracks[ mActiveTrack ].enabled != 1) { - mState.tracks[ mActiveTrack ].enabled = 1; - LOGV("enable(%d)", mActiveTrack); - invalidateState(1<<mActiveTrack); - } - } break; - default: - return NAME_NOT_FOUND; - } - return NO_ERROR; -} - -status_t AudioMixer::disable(int name) -{ - switch (name) { - case MIXING: { - if (mState.tracks[ mActiveTrack ].enabled != 0) { - mState.tracks[ mActiveTrack ].enabled = 0; - LOGV("disable(%d)", mActiveTrack); - invalidateState(1<<mActiveTrack); - } - } break; - default: - return NAME_NOT_FOUND; - } - return NO_ERROR; -} - -status_t AudioMixer::setActiveTrack(int track) -{ - if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) { - return BAD_VALUE; - } - mActiveTrack = track - TRACK0; - return NO_ERROR; -} - -status_t AudioMixer::setParameter(int target, int name, int value) -{ - switch (target) { - case TRACK: - if (name == CHANNEL_COUNT) { - if ((uint32_t(value) <= MAX_NUM_CHANNELS) && (value)) { - if (mState.tracks[ mActiveTrack ].channelCount != value) { - mState.tracks[ mActiveTrack ].channelCount = value; - LOGV("setParameter(TRACK, CHANNEL_COUNT, %d)", value); - invalidateState(1<<mActiveTrack); - } - return NO_ERROR; - } - } - break; - case RESAMPLE: - if (name == SAMPLE_RATE) { - if (value > 0) { - track_t& track = mState.tracks[ mActiveTrack ]; - if (track.setResampler(uint32_t(value), mSampleRate)) { - LOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)", - uint32_t(value)); - invalidateState(1<<mActiveTrack); - } - return NO_ERROR; - } - } - break; - case RAMP_VOLUME: - case VOLUME: - if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) { - track_t& track = mState.tracks[ mActiveTrack ]; - if (track.volume[name-VOLUME0] != value) { - track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16; - track.volume[name-VOLUME0] = value; - if (target == VOLUME) { - track.prevVolume[name-VOLUME0] = value << 16; - track.volumeInc[name-VOLUME0] = 0; - } else { - int32_t d = (value<<16) - track.prevVolume[name-VOLUME0]; - int32_t volInc = d / int32_t(mState.frameCount); - track.volumeInc[name-VOLUME0] = volInc; - if (volInc == 0) { - track.prevVolume[name-VOLUME0] = value << 16; - } - } - invalidateState(1<<mActiveTrack); - } - return NO_ERROR; - } - break; - } - return BAD_VALUE; -} - -bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate) -{ - if (value!=devSampleRate || resampler) { - if (sampleRate != value) { - sampleRate = value; - if (resampler == 0) { - resampler = AudioResampler::create( - format, channelCount, devSampleRate); - } - return true; - } - } - return false; -} - -bool AudioMixer::track_t::doesResample() const -{ - return resampler != 0; -} - -inline -void AudioMixer::track_t::adjustVolumeRamp() -{ - for (int i=0 ; i<2 ; i++) { - if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) || - ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) { - volumeInc[i] = 0; - prevVolume[i] = volume[i]<<16; - } - } -} - - -status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer) -{ - mState.tracks[ mActiveTrack ].bufferProvider = buffer; - return NO_ERROR; -} - - - -void AudioMixer::process(void* output) -{ - mState.hook(&mState, output); -} - - -void AudioMixer::process__validate(state_t* state, void* output) -{ - LOGW_IF(!state->needsChanged, - "in process__validate() but nothing's invalid"); - - uint32_t changed = state->needsChanged; - state->needsChanged = 0; // clear the validation flag - - // recompute which tracks are enabled / disabled - uint32_t enabled = 0; - uint32_t disabled = 0; - while (changed) { - const int i = 31 - __builtin_clz(changed); - const uint32_t mask = 1<<i; - changed &= ~mask; - track_t& t = state->tracks[i]; - (t.enabled ? enabled : disabled) |= mask; - } - state->enabledTracks &= ~disabled; - state->enabledTracks |= enabled; - - // compute everything we need... - int countActiveTracks = 0; - int all16BitsStereoNoResample = 1; - int resampling = 0; - int volumeRamp = 0; - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - - countActiveTracks++; - track_t& t = state->tracks[i]; - uint32_t n = 0; - n |= NEEDS_CHANNEL_1 + t.channelCount - 1; - n |= NEEDS_FORMAT_16; - n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED; - - if (t.volumeInc[0]|t.volumeInc[1]) { - volumeRamp = 1; - } else if (!t.doesResample() && t.volumeRL == 0) { - n |= NEEDS_MUTE_ENABLED; - } - t.needs = n; - - if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) { - t.hook = track__nop; - } else { - if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { - all16BitsStereoNoResample = 0; - resampling = 1; - t.hook = track__genericResample; - } else { - if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){ - t.hook = track__16BitsMono; - all16BitsStereoNoResample = 0; - } - if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){ - t.hook = track__16BitsStereo; - } - } - } - } - - // select the processing hooks - state->hook = process__nop; - if (countActiveTracks) { - if (resampling) { - if (!state->outputTemp) { - state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; - } - if (!state->resampleTemp) { - state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; - } - state->hook = process__genericResampling; - } else { - if (state->outputTemp) { - delete [] state->outputTemp; - state->outputTemp = 0; - } - if (state->resampleTemp) { - delete [] state->resampleTemp; - state->resampleTemp = 0; - } - state->hook = process__genericNoResampling; - if (all16BitsStereoNoResample && !volumeRamp) { - if (countActiveTracks == 1) { - state->hook = process__OneTrack16BitsStereoNoResampling; - } - } - } - } - - LOGV("mixer configuration change: %d activeTracks (%08x) " - "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d", - countActiveTracks, state->enabledTracks, - all16BitsStereoNoResample, resampling, volumeRamp); - - state->hook(state, output); - - // Now that the volume ramp has been done, set optimal state and - // track hooks for subsequent mixer process - if (countActiveTracks) { - int allMuted = 1; - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - if (!t.doesResample() && t.volumeRL == 0) - { - t.needs |= NEEDS_MUTE_ENABLED; - t.hook = track__nop; - } else { - allMuted = 0; - } - } - if (allMuted) { - state->hook = process__nop; - } else if (!resampling && all16BitsStereoNoResample) { - if (countActiveTracks == 1) { - state->hook = process__OneTrack16BitsStereoNoResampling; - } - } - } -} - -static inline -int32_t mulAdd(int16_t in, int16_t v, int32_t a) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - asm( "smlabb %[out], %[in], %[v], %[a] \n" - : [out]"=r"(out) - : [in]"%r"(in), [v]"r"(v), [a]"r"(a) - : ); - return out; -#else - return a + in * int32_t(v); -#endif -} - -static inline -int32_t mul(int16_t in, int16_t v) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - asm( "smulbb %[out], %[in], %[v] \n" - : [out]"=r"(out) - : [in]"%r"(in), [v]"r"(v) - : ); - return out; -#else - return in * int32_t(v); -#endif -} - -static inline -int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - if (left) { - asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) - : ); - } else { - asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) - : ); - } - return out; -#else - if (left) { - return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF); - } else { - return a + int16_t(inRL>>16) * int16_t(vRL>>16); - } -#endif -} - -static inline -int32_t mulRL(int left, uint32_t inRL, uint32_t vRL) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - if (left) { - asm( "smulbb %[out], %[inRL], %[vRL] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [vRL]"r"(vRL) - : ); - } else { - asm( "smultt %[out], %[inRL], %[vRL] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [vRL]"r"(vRL) - : ); - } - return out; -#else - if (left) { - return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF); - } else { - return int16_t(inRL>>16) * int16_t(vRL>>16); - } -#endif -} - - -void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp) -{ - t->resampler->setSampleRate(t->sampleRate); - - // ramp gain - resample to temp buffer and scale/mix in 2nd step - if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { - t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN); - memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t)); - t->resampler->resample(temp, outFrameCount, t->bufferProvider); - volumeRampStereo(t, out, outFrameCount, temp); - } - - // constant gain - else { - t->resampler->setVolume(t->volume[0], t->volume[1]); - t->resampler->resample(out, outFrameCount, t->bufferProvider); - } -} - -void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp) -{ -} - -void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) -{ - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", - // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], - // (vl + vlInc*frameCount)/65536.0f, frameCount); - - // ramp volume - do { - *out++ += (vl >> 16) * (*temp++ >> 12); - *out++ += (vr >> 16) * (*temp++ >> 12); - vl += vlInc; - vr += vrInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(); -} - -void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) -{ - int16_t const *in = static_cast<int16_t const *>(t->in); - - // ramp gain - if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", - // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], - // (vl + vlInc*frameCount)/65536.0f, frameCount); - - do { - *out++ += (vl >> 16) * (int32_t) *in++; - *out++ += (vr >> 16) * (int32_t) *in++; - vl += vlInc; - vr += vrInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(); - } - - // constant gain - else { - const uint32_t vrl = t->volumeRL; - do { - uint32_t rl = *reinterpret_cast<uint32_t const *>(in); - in += 2; - out[0] = mulAddRL(1, rl, vrl, out[0]); - out[1] = mulAddRL(0, rl, vrl, out[1]); - out += 2; - } while (--frameCount); - } - t->in = in; -} - -void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) -{ - int16_t const *in = static_cast<int16_t const *>(t->in); - - // ramp gain - if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", - // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], - // (vl + vlInc*frameCount)/65536.0f, frameCount); - - do { - int32_t l = *in++; - *out++ += (vl >> 16) * l; - *out++ += (vr >> 16) * l; - vl += vlInc; - vr += vrInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(); - } - // constant gain - else { - const int16_t vl = t->volume[0]; - const int16_t vr = t->volume[1]; - do { - int16_t l = *in++; - out[0] = mulAdd(l, vl, out[0]); - out[1] = mulAdd(l, vr, out[1]); - out += 2; - } while (--frameCount); - } - t->in = in; -} - -inline -void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c) -{ - for (size_t i=0 ; i<c ; i++) { - int32_t l = *sums++; - int32_t r = *sums++; - int32_t nl = l >> 12; - int32_t nr = r >> 12; - l = clamp16(nl); - r = clamp16(nr); - *out++ = (r<<16) | (l & 0xFFFF); - } -} - -// no-op case -void AudioMixer::process__nop(state_t* state, void* output) -{ - // this assumes output 16 bits stereo, no resampling - memset(output, 0, state->frameCount*4); - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - size_t outFrames = state->frameCount; - while (outFrames) { - t.buffer.frameCount = outFrames; - t.bufferProvider->getNextBuffer(&t.buffer); - if (!t.buffer.raw) break; - outFrames -= t.buffer.frameCount; - t.bufferProvider->releaseBuffer(&t.buffer); - } - } -} - -// generic code without resampling -void AudioMixer::process__genericNoResampling(state_t* state, void* output) -{ - int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32))); - - // acquire each track's buffer - uint32_t enabledTracks = state->enabledTracks; - uint32_t en = enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - t.buffer.frameCount = state->frameCount; - t.bufferProvider->getNextBuffer(&t.buffer); - t.frameCount = t.buffer.frameCount; - t.in = t.buffer.raw; - // t.in == NULL can happen if the track was flushed just after having - // been enabled for mixing. - if (t.in == NULL) - enabledTracks &= ~(1<<i); - } - - // this assumes output 16 bits stereo, no resampling - int32_t* out = static_cast<int32_t*>(output); - size_t numFrames = state->frameCount; - do { - memset(outTemp, 0, sizeof(outTemp)); - - en = enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - size_t outFrames = BLOCKSIZE; - - while (outFrames) { - size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount; - if (inFrames) { - (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp); - t.frameCount -= inFrames; - outFrames -= inFrames; - } - if (t.frameCount == 0 && outFrames) { - t.bufferProvider->releaseBuffer(&t.buffer); - t.buffer.frameCount = numFrames - (BLOCKSIZE - outFrames); - t.bufferProvider->getNextBuffer(&t.buffer); - t.in = t.buffer.raw; - if (t.in == NULL) { - enabledTracks &= ~(1<<i); - break; - } - t.frameCount = t.buffer.frameCount; - } - } - } - - ditherAndClamp(out, outTemp, BLOCKSIZE); - out += BLOCKSIZE; - numFrames -= BLOCKSIZE; - } while (numFrames); - - - // release each track's buffer - en = enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - t.bufferProvider->releaseBuffer(&t.buffer); - } -} - -// generic code with resampling -void AudioMixer::process__genericResampling(state_t* state, void* output) -{ - int32_t* const outTemp = state->outputTemp; - const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount; - memset(outTemp, 0, size); - - int32_t* out = static_cast<int32_t*>(output); - size_t numFrames = state->frameCount; - - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - - // this is a little goofy, on the resampling case we don't - // acquire/release the buffers because it's done by - // the resampler. - if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { - (t.hook)(&t, outTemp, numFrames, state->resampleTemp); - } else { - - size_t outFrames = numFrames; - - while (outFrames) { - t.buffer.frameCount = outFrames; - t.bufferProvider->getNextBuffer(&t.buffer); - t.in = t.buffer.raw; - // t.in == NULL can happen if the track was flushed just after having - // been enabled for mixing. - if (t.in == NULL) break; - - (t.hook)(&t, outTemp + (numFrames-outFrames)*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp); - outFrames -= t.buffer.frameCount; - t.bufferProvider->releaseBuffer(&t.buffer); - } - } - } - - ditherAndClamp(out, outTemp, numFrames); -} - -// one track, 16 bits stereo without resampling is the most common case -void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, void* output) -{ - const int i = 31 - __builtin_clz(state->enabledTracks); - const track_t& t = state->tracks[i]; - - AudioBufferProvider::Buffer& b(t.buffer); - - int32_t* out = static_cast<int32_t*>(output); - size_t numFrames = state->frameCount; - - const int16_t vl = t.volume[0]; - const int16_t vr = t.volume[1]; - const uint32_t vrl = t.volumeRL; - while (numFrames) { - b.frameCount = numFrames; - t.bufferProvider->getNextBuffer(&b); - int16_t const *in = b.i16; - - // in == NULL can happen if the track was flushed just after having - // been enabled for mixing. - if (in == NULL) { - memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t)); - return; - } - size_t outFrames = b.frameCount; - - if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) { - // volume is boosted, so we might need to clamp even though - // we process only one track. - do { - uint32_t rl = *reinterpret_cast<uint32_t const *>(in); - in += 2; - int32_t l = mulRL(1, rl, vrl) >> 12; - int32_t r = mulRL(0, rl, vrl) >> 12; - // clamping... - l = clamp16(l); - r = clamp16(r); - *out++ = (r<<16) | (l & 0xFFFF); - } while (--outFrames); - } else { - do { - uint32_t rl = *reinterpret_cast<uint32_t const *>(in); - in += 2; - int32_t l = mulRL(1, rl, vrl) >> 12; - int32_t r = mulRL(0, rl, vrl) >> 12; - *out++ = (r<<16) | (l & 0xFFFF); - } while (--outFrames); - } - numFrames -= b.frameCount; - t.bufferProvider->releaseBuffer(&b); - } -} - -// 2 tracks is also a common case -void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state, void* output) -{ - int i; - uint32_t en = state->enabledTracks; - - i = 31 - __builtin_clz(en); - const track_t& t0 = state->tracks[i]; - AudioBufferProvider::Buffer& b0(t0.buffer); - - en &= ~(1<<i); - i = 31 - __builtin_clz(en); - const track_t& t1 = state->tracks[i]; - AudioBufferProvider::Buffer& b1(t1.buffer); - - int16_t const *in0; - const int16_t vl0 = t0.volume[0]; - const int16_t vr0 = t0.volume[1]; - size_t frameCount0 = 0; - - int16_t const *in1; - const int16_t vl1 = t1.volume[0]; - const int16_t vr1 = t1.volume[1]; - size_t frameCount1 = 0; - - int32_t* out = static_cast<int32_t*>(output); - size_t numFrames = state->frameCount; - int16_t const *buff = NULL; - - - while (numFrames) { - - if (frameCount0 == 0) { - b0.frameCount = numFrames; - t0.bufferProvider->getNextBuffer(&b0); - if (b0.i16 == NULL) { - if (buff == NULL) { - buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; - } - in0 = buff; - b0.frameCount = numFrames; - } else { - in0 = b0.i16; - } - frameCount0 = b0.frameCount; - } - if (frameCount1 == 0) { - b1.frameCount = numFrames; - t1.bufferProvider->getNextBuffer(&b1); - if (b1.i16 == NULL) { - if (buff == NULL) { - buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; - } - in1 = buff; - b1.frameCount = numFrames; - } else { - in1 = b1.i16; - } - frameCount1 = b1.frameCount; - } - - size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1; - - numFrames -= outFrames; - frameCount0 -= outFrames; - frameCount1 -= outFrames; - - do { - int32_t l0 = *in0++; - int32_t r0 = *in0++; - l0 = mul(l0, vl0); - r0 = mul(r0, vr0); - int32_t l = *in1++; - int32_t r = *in1++; - l = mulAdd(l, vl1, l0) >> 12; - r = mulAdd(r, vr1, r0) >> 12; - // clamping... - l = clamp16(l); - r = clamp16(r); - *out++ = (r<<16) | (l & 0xFFFF); - } while (--outFrames); - - if (frameCount0 == 0) { - t0.bufferProvider->releaseBuffer(&b0); - } - if (frameCount1 == 0) { - t1.bufferProvider->releaseBuffer(&b1); - } - } - - if (buff != NULL) { - delete [] buff; - } -} - -// ---------------------------------------------------------------------------- -}; // namespace android - diff --git a/libs/audioflinger/AudioMixer.h b/libs/audioflinger/AudioMixer.h deleted file mode 100644 index 72ca28a..0000000 --- a/libs/audioflinger/AudioMixer.h +++ /dev/null @@ -1,192 +0,0 @@ -/* //device/include/server/AudioFlinger/AudioMixer.h -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef ANDROID_AUDIO_MIXER_H -#define ANDROID_AUDIO_MIXER_H - -#include <stdint.h> -#include <sys/types.h> - -#include "AudioBufferProvider.h" -#include "AudioResampler.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// ---------------------------------------------------------------------------- - -class AudioMixer -{ -public: - AudioMixer(size_t frameCount, uint32_t sampleRate); - - ~AudioMixer(); - - static const uint32_t MAX_NUM_TRACKS = 32; - static const uint32_t MAX_NUM_CHANNELS = 2; - - static const uint16_t UNITY_GAIN = 0x1000; - - enum { // names - - // track units (32 units) - TRACK0 = 0x1000, - - // enable/disable - MIXING = 0x2000, - - // setParameter targets - TRACK = 0x3000, - RESAMPLE = 0x3001, - RAMP_VOLUME = 0x3002, // ramp to new volume - VOLUME = 0x3003, // don't ramp - - // set Parameter names - // for target TRACK - CHANNEL_COUNT = 0x4000, - FORMAT = 0x4001, - // for TARGET RESAMPLE - SAMPLE_RATE = 0x4100, - // for TARGET VOLUME (8 channels max) - VOLUME0 = 0x4200, - VOLUME1 = 0x4201, - }; - - - int getTrackName(); - void deleteTrackName(int name); - - status_t enable(int name); - status_t disable(int name); - - status_t setActiveTrack(int track); - status_t setParameter(int target, int name, int value); - - status_t setBufferProvider(AudioBufferProvider* bufferProvider); - void process(void* output); - - uint32_t trackNames() const { return mTrackNames; } - -private: - - enum { - NEEDS_CHANNEL_COUNT__MASK = 0x00000003, - NEEDS_FORMAT__MASK = 0x000000F0, - NEEDS_MUTE__MASK = 0x00000100, - NEEDS_RESAMPLE__MASK = 0x00001000, - }; - - enum { - NEEDS_CHANNEL_1 = 0x00000000, - NEEDS_CHANNEL_2 = 0x00000001, - - NEEDS_FORMAT_16 = 0x00000010, - - NEEDS_MUTE_DISABLED = 0x00000000, - NEEDS_MUTE_ENABLED = 0x00000100, - - NEEDS_RESAMPLE_DISABLED = 0x00000000, - NEEDS_RESAMPLE_ENABLED = 0x00001000, - }; - - static inline int32_t applyVolume(int32_t in, int32_t v) { - return in * v; - } - - - struct state_t; - - typedef void (*mix_t)(state_t* state, void* output); - - static const int BLOCKSIZE = 16; // 4 cache lines - - struct track_t { - uint32_t needs; - - union { - int16_t volume[2]; // [0]3.12 fixed point - int32_t volumeRL; - }; - - int32_t prevVolume[2]; - - int32_t volumeInc[2]; - - uint16_t frameCount; - - uint8_t channelCount : 4; - uint8_t enabled : 1; - uint8_t reserved0 : 3; - uint8_t format; - - AudioBufferProvider* bufferProvider; - mutable AudioBufferProvider::Buffer buffer; - - void (*hook)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp); - void const* in; // current location in buffer - - AudioResampler* resampler; - uint32_t sampleRate; - - bool setResampler(uint32_t sampleRate, uint32_t devSampleRate); - bool doesResample() const; - void adjustVolumeRamp(); - }; - - // pad to 32-bytes to fill cache line - struct state_t { - uint32_t enabledTracks; - uint32_t needsChanged; - size_t frameCount; - mix_t hook; - int32_t *outputTemp; - int32_t *resampleTemp; - int32_t reserved[2]; - track_t tracks[32]; __attribute__((aligned(32))); - }; - - int mActiveTrack; - uint32_t mTrackNames; - const uint32_t mSampleRate; - - state_t mState __attribute__((aligned(32))); - - void invalidateState(uint32_t mask); - - static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp); - static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp); - static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp); - static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp); - static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp); - static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c); - - static void process__validate(state_t* state, void* output); - static void process__nop(state_t* state, void* output); - static void process__genericNoResampling(state_t* state, void* output); - static void process__genericResampling(state_t* state, void* output); - static void process__OneTrack16BitsStereoNoResampling(state_t* state, void* output); - static void process__TwoTracks16BitsStereoNoResampling(state_t* state, void* output); -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_AUDIO_MIXER_H diff --git a/libs/audioflinger/AudioResampler.cpp b/libs/audioflinger/AudioResampler.cpp deleted file mode 100644 index 5dabacb..0000000 --- a/libs/audioflinger/AudioResampler.cpp +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "AudioResampler" -//#define LOG_NDEBUG 0 - -#include <stdint.h> -#include <stdlib.h> -#include <sys/types.h> -#include <cutils/log.h> -#include <cutils/properties.h> -#include "AudioResampler.h" -#include "AudioResamplerSinc.h" -#include "AudioResamplerCubic.h" - -namespace android { - -#ifdef __ARM_ARCH_5E__ // optimized asm option - #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1 -#endif // __ARM_ARCH_5E__ -// ---------------------------------------------------------------------------- - -class AudioResamplerOrder1 : public AudioResampler { -public: - AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) : - AudioResampler(bitDepth, inChannelCount, sampleRate), mX0L(0), mX0R(0) { - } - virtual void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); -private: - // number of bits used in interpolation multiply - 15 bits avoids overflow - static const int kNumInterpBits = 15; - - // bits to shift the phase fraction down to avoid overflow - static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits; - - void init() {} - void resampleMono16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); - void resampleStereo16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); -#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 - void AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, - size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, - uint32_t &phaseFraction, uint32_t phaseIncrement); - void AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, - size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, - uint32_t &phaseFraction, uint32_t phaseIncrement); -#endif // ASM_ARM_RESAMP1 - - static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) { - return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits); - } - static inline void Advance(size_t* index, uint32_t* frac, uint32_t inc) { - *frac += inc; - *index += (size_t)(*frac >> kNumPhaseBits); - *frac &= kPhaseMask; - } - int mX0L; - int mX0R; -}; - -// ---------------------------------------------------------------------------- -AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, - int32_t sampleRate, int quality) { - - // can only create low quality resample now - AudioResampler* resampler; - - char value[PROPERTY_VALUE_MAX]; - if (property_get("af.resampler.quality", value, 0)) { - quality = atoi(value); - LOGD("forcing AudioResampler quality to %d", quality); - } - - if (quality == DEFAULT) - quality = LOW_QUALITY; - - switch (quality) { - default: - case LOW_QUALITY: - LOGV("Create linear Resampler"); - resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate); - break; - case MED_QUALITY: - LOGV("Create cubic Resampler"); - resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate); - break; - case HIGH_QUALITY: - LOGV("Create sinc Resampler"); - resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate); - break; - } - - // initialize resampler - resampler->init(); - return resampler; -} - -AudioResampler::AudioResampler(int bitDepth, int inChannelCount, - int32_t sampleRate) : - mBitDepth(bitDepth), mChannelCount(inChannelCount), - mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0), - mPhaseFraction(0) { - // sanity check on format - if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) { - LOGE("Unsupported sample format, %d bits, %d channels", bitDepth, - inChannelCount); - // LOG_ASSERT(0); - } - - // initialize common members - mVolume[0] = mVolume[1] = 0; - mBuffer.frameCount = 0; - - // save format for quick lookup - if (inChannelCount == 1) { - mFormat = MONO_16_BIT; - } else { - mFormat = STEREO_16_BIT; - } -} - -AudioResampler::~AudioResampler() { -} - -void AudioResampler::setSampleRate(int32_t inSampleRate) { - mInSampleRate = inSampleRate; - mPhaseIncrement = (uint32_t)((kPhaseMultiplier * inSampleRate) / mSampleRate); -} - -void AudioResampler::setVolume(int16_t left, int16_t right) { - // TODO: Implement anti-zipper filter - mVolume[0] = left; - mVolume[1] = right; -} - -// ---------------------------------------------------------------------------- - -void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - // should never happen, but we overflow if it does - // LOG_ASSERT(outFrameCount < 32767); - - // select the appropriate resampler - switch (mChannelCount) { - case 1: - resampleMono16(out, outFrameCount, provider); - break; - case 2: - resampleStereo16(out, outFrameCount, provider); - break; - } -} - -void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - int32_t vl = mVolume[0]; - int32_t vr = mVolume[1]; - - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n", - // outFrameCount, inputIndex, phaseFraction, phaseIncrement); - - while (outputIndex < outputSampleCount) { - - // buffer is empty, fetch a new one - while (mBuffer.frameCount == 0) { - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) { - goto resampleStereo16_exit; - } - - // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount); - if (mBuffer.frameCount > inputIndex) break; - - inputIndex -= mBuffer.frameCount; - mX0L = mBuffer.i16[mBuffer.frameCount*2-2]; - mX0R = mBuffer.i16[mBuffer.frameCount*2-1]; - provider->releaseBuffer(&mBuffer); - // mBuffer.frameCount == 0 now so we reload a new buffer - } - - int16_t *in = mBuffer.i16; - - // handle boundary case - while (inputIndex == 0) { - // LOGE("boundary case\n"); - out[outputIndex++] += vl * Interp(mX0L, in[0], phaseFraction); - out[outputIndex++] += vr * Interp(mX0R, in[1], phaseFraction); - Advance(&inputIndex, &phaseFraction, phaseIncrement); - if (outputIndex == outputSampleCount) - break; - } - - // process input samples - // LOGE("general case\n"); - -#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 - if (inputIndex + 2 < mBuffer.frameCount) { - int32_t* maxOutPt; - int32_t maxInIdx; - - maxOutPt = out + (outputSampleCount - 2); // 2 because 2 frames per loop - maxInIdx = mBuffer.frameCount - 2; - AsmStereo16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr, - phaseFraction, phaseIncrement); - } -#endif // ASM_ARM_RESAMP1 - - while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) { - out[outputIndex++] += vl * Interp(in[inputIndex*2-2], - in[inputIndex*2], phaseFraction); - out[outputIndex++] += vr * Interp(in[inputIndex*2-1], - in[inputIndex*2+1], phaseFraction); - Advance(&inputIndex, &phaseFraction, phaseIncrement); - } - - // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); - - // if done with buffer, save samples - if (inputIndex >= mBuffer.frameCount) { - inputIndex -= mBuffer.frameCount; - - // LOGE("buffer done, new input index %d", inputIndex); - - mX0L = mBuffer.i16[mBuffer.frameCount*2-2]; - mX0R = mBuffer.i16[mBuffer.frameCount*2-1]; - provider->releaseBuffer(&mBuffer); - - // verify that the releaseBuffer resets the buffer frameCount - // LOG_ASSERT(mBuffer.frameCount == 0); - } - } - - // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); - -resampleStereo16_exit: - // save state - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - int32_t vl = mVolume[0]; - int32_t vr = mVolume[1]; - - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n", - // outFrameCount, inputIndex, phaseFraction, phaseIncrement); - while (outputIndex < outputSampleCount) { - // buffer is empty, fetch a new one - while (mBuffer.frameCount == 0) { - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) { - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; - goto resampleMono16_exit; - } - // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount); - if (mBuffer.frameCount > inputIndex) break; - - inputIndex -= mBuffer.frameCount; - mX0L = mBuffer.i16[mBuffer.frameCount-1]; - provider->releaseBuffer(&mBuffer); - // mBuffer.frameCount == 0 now so we reload a new buffer - } - int16_t *in = mBuffer.i16; - - // handle boundary case - while (inputIndex == 0) { - // LOGE("boundary case\n"); - int32_t sample = Interp(mX0L, in[0], phaseFraction); - out[outputIndex++] += vl * sample; - out[outputIndex++] += vr * sample; - Advance(&inputIndex, &phaseFraction, phaseIncrement); - if (outputIndex == outputSampleCount) - break; - } - - // process input samples - // LOGE("general case\n"); - -#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 - if (inputIndex + 2 < mBuffer.frameCount) { - int32_t* maxOutPt; - int32_t maxInIdx; - - maxOutPt = out + (outputSampleCount - 2); - maxInIdx = (int32_t)mBuffer.frameCount - 2; - AsmMono16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr, - phaseFraction, phaseIncrement); - } -#endif // ASM_ARM_RESAMP1 - - while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) { - int32_t sample = Interp(in[inputIndex-1], in[inputIndex], - phaseFraction); - out[outputIndex++] += vl * sample; - out[outputIndex++] += vr * sample; - Advance(&inputIndex, &phaseFraction, phaseIncrement); - } - - - // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); - - // if done with buffer, save samples - if (inputIndex >= mBuffer.frameCount) { - inputIndex -= mBuffer.frameCount; - - // LOGE("buffer done, new input index %d", inputIndex); - - mX0L = mBuffer.i16[mBuffer.frameCount-1]; - provider->releaseBuffer(&mBuffer); - - // verify that the releaseBuffer resets the buffer frameCount - // LOG_ASSERT(mBuffer.frameCount == 0); - } - } - - // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); - -resampleMono16_exit: - // save state - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 - -/******************************************************************* -* -* AsmMono16Loop -* asm optimized monotonic loop version; one loop is 2 frames -* Input: -* in : pointer on input samples -* maxOutPt : pointer on first not filled -* maxInIdx : index on first not used -* outputIndex : pointer on current output index -* out : pointer on output buffer -* inputIndex : pointer on current input index -* vl, vr : left and right gain -* phaseFraction : pointer on current phase fraction -* phaseIncrement -* Ouput: -* outputIndex : -* out : updated buffer -* inputIndex : index of next to use -* phaseFraction : phase fraction for next interpolation -* -*******************************************************************/ -void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, - size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, - uint32_t &phaseFraction, uint32_t phaseIncrement) -{ -#define MO_PARAM5 "36" // offset of parameter 5 (outputIndex) - - asm( - "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" - // get parameters - " ldr r6, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction - " ldr r6, [r6]\n" // phaseFraction - " ldr r7, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex - " ldr r7, [r7]\n" // inputIndex - " ldr r8, [sp, #" MO_PARAM5 " + 4]\n" // out - " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex - " ldr r0, [r0]\n" // outputIndex - " add r8, r0, asl #2\n" // curOut - " ldr r9, [sp, #" MO_PARAM5 " + 24]\n" // phaseIncrement - " ldr r10, [sp, #" MO_PARAM5 " + 12]\n" // vl - " ldr r11, [sp, #" MO_PARAM5 " + 16]\n" // vr - - // r0 pin, x0, Samp - - // r1 in - // r2 maxOutPt - // r3 maxInIdx - - // r4 x1, i1, i3, Out1 - // r5 out0 - - // r6 frac - // r7 inputIndex - // r8 curOut - - // r9 inc - // r10 vl - // r11 vr - - // r12 - // r13 sp - // r14 - - // the following loop works on 2 frames - - ".Y4L01:\n" - " cmp r8, r2\n" // curOut - maxCurOut - " bcs .Y4L02\n" - -#define MO_ONE_FRAME \ - " add r0, r1, r7, asl #1\n" /* in + inputIndex */\ - " ldrsh r4, [r0]\n" /* in[inputIndex] */\ - " ldr r5, [r8]\n" /* out[outputIndex] */\ - " ldrsh r0, [r0, #-2]\n" /* in[inputIndex-1] */\ - " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\ - " sub r4, r4, r0\n" /* in[inputIndex] - in[inputIndex-1] */\ - " mov r4, r4, lsl #2\n" /* <<2 */\ - " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\ - " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\ - " add r0, r0, r4\n" /* x0 - (..) */\ - " mla r5, r0, r10, r5\n" /* vl*interp + out[] */\ - " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\ - " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\ - " mla r4, r0, r11, r4\n" /* vr*interp + out[] */\ - " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */\ - " str r4, [r8], #4\n" /* out[outputIndex++] = ... */ - - MO_ONE_FRAME // frame 1 - MO_ONE_FRAME // frame 2 - - " cmp r7, r3\n" // inputIndex - maxInIdx - " bcc .Y4L01\n" - ".Y4L02:\n" - - " bic r6, r6, #0xC0000000\n" // phaseFraction & ... - // save modified values - " ldr r0, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction - " str r6, [r0]\n" // phaseFraction - " ldr r0, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex - " str r7, [r0]\n" // inputIndex - " ldr r0, [sp, #" MO_PARAM5 " + 4]\n" // out - " sub r8, r0\n" // curOut - out - " asr r8, #2\n" // new outputIndex - " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex - " str r8, [r0]\n" // save outputIndex - - " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}\n" - ); -} - -/******************************************************************* -* -* AsmStereo16Loop -* asm optimized stereo loop version; one loop is 2 frames -* Input: -* in : pointer on input samples -* maxOutPt : pointer on first not filled -* maxInIdx : index on first not used -* outputIndex : pointer on current output index -* out : pointer on output buffer -* inputIndex : pointer on current input index -* vl, vr : left and right gain -* phaseFraction : pointer on current phase fraction -* phaseIncrement -* Ouput: -* outputIndex : -* out : updated buffer -* inputIndex : index of next to use -* phaseFraction : phase fraction for next interpolation -* -*******************************************************************/ -void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, - size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, - uint32_t &phaseFraction, uint32_t phaseIncrement) -{ -#define ST_PARAM5 "40" // offset of parameter 5 (outputIndex) - asm( - "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n" - // get parameters - " ldr r6, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction - " ldr r6, [r6]\n" // phaseFraction - " ldr r7, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex - " ldr r7, [r7]\n" // inputIndex - " ldr r8, [sp, #" ST_PARAM5 " + 4]\n" // out - " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex - " ldr r0, [r0]\n" // outputIndex - " add r8, r0, asl #2\n" // curOut - " ldr r9, [sp, #" ST_PARAM5 " + 24]\n" // phaseIncrement - " ldr r10, [sp, #" ST_PARAM5 " + 12]\n" // vl - " ldr r11, [sp, #" ST_PARAM5 " + 16]\n" // vr - - // r0 pin, x0, Samp - - // r1 in - // r2 maxOutPt - // r3 maxInIdx - - // r4 x1, i1, i3, out1 - // r5 out0 - - // r6 frac - // r7 inputIndex - // r8 curOut - - // r9 inc - // r10 vl - // r11 vr - - // r12 temporary - // r13 sp - // r14 - - ".Y5L01:\n" - " cmp r8, r2\n" // curOut - maxCurOut - " bcs .Y5L02\n" - -#define ST_ONE_FRAME \ - " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\ -\ - " add r0, r1, r7, asl #2\n" /* in + 2*inputIndex */\ -\ - " ldrsh r4, [r0]\n" /* in[2*inputIndex] */\ - " ldr r5, [r8]\n" /* out[outputIndex] */\ - " ldrsh r12, [r0, #-4]\n" /* in[2*inputIndex-2] */\ - " sub r4, r4, r12\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\ - " mov r4, r4, lsl #2\n" /* <<2 */\ - " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\ - " add r12, r12, r4\n" /* x0 - (..) */\ - " mla r5, r12, r10, r5\n" /* vl*interp + out[] */\ - " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\ - " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\ -\ - " ldrsh r12, [r0, #+2]\n" /* in[2*inputIndex+1] */\ - " ldrsh r0, [r0, #-2]\n" /* in[2*inputIndex-1] */\ - " sub r12, r12, r0\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\ - " mov r12, r12, lsl #2\n" /* <<2 */\ - " smulwt r12, r12, r6\n" /* (x1-x0)*.. */\ - " add r12, r0, r12\n" /* x0 - (..) */\ - " mla r4, r12, r11, r4\n" /* vr*interp + out[] */\ - " str r4, [r8], #4\n" /* out[outputIndex++] = ... */\ -\ - " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\ - " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */ - - ST_ONE_FRAME // frame 1 - ST_ONE_FRAME // frame 1 - - " cmp r7, r3\n" // inputIndex - maxInIdx - " bcc .Y5L01\n" - ".Y5L02:\n" - - " bic r6, r6, #0xC0000000\n" // phaseFraction & ... - // save modified values - " ldr r0, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction - " str r6, [r0]\n" // phaseFraction - " ldr r0, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex - " str r7, [r0]\n" // inputIndex - " ldr r0, [sp, #" ST_PARAM5 " + 4]\n" // out - " sub r8, r0\n" // curOut - out - " asr r8, #2\n" // new outputIndex - " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex - " str r8, [r0]\n" // save outputIndex - - " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}\n" - ); -} - -#endif // ASM_ARM_RESAMP1 - - -// ---------------------------------------------------------------------------- -} -; // namespace android - diff --git a/libs/audioflinger/AudioResampler.h b/libs/audioflinger/AudioResampler.h deleted file mode 100644 index 39656c0..0000000 --- a/libs/audioflinger/AudioResampler.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_AUDIO_RESAMPLER_H -#define ANDROID_AUDIO_RESAMPLER_H - -#include <stdint.h> -#include <sys/types.h> - -#include "AudioBufferProvider.h" - -namespace android { -// ---------------------------------------------------------------------------- - -class AudioResampler { -public: - // Determines quality of SRC. - // LOW_QUALITY: linear interpolator (1st order) - // MED_QUALITY: cubic interpolator (3rd order) - // HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz) - // NOTE: high quality SRC will only be supported for - // certain fixed rate conversions. Sample rate cannot be - // changed dynamically. - enum src_quality { - DEFAULT=0, - LOW_QUALITY=1, - MED_QUALITY=2, - HIGH_QUALITY=3 - }; - - static AudioResampler* create(int bitDepth, int inChannelCount, - int32_t sampleRate, int quality=DEFAULT); - - virtual ~AudioResampler(); - - virtual void init() = 0; - virtual void setSampleRate(int32_t inSampleRate); - virtual void setVolume(int16_t left, int16_t right); - - virtual void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) = 0; - -protected: - // number of bits for phase fraction - 30 bits allows nearly 2x downsampling - static const int kNumPhaseBits = 30; - - // phase mask for fraction - static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1; - - // multiplier to calculate fixed point phase increment - static const double kPhaseMultiplier = 1L << kNumPhaseBits; - - enum format {MONO_16_BIT, STEREO_16_BIT}; - AudioResampler(int bitDepth, int inChannelCount, int32_t sampleRate); - - // prevent copying - AudioResampler(const AudioResampler&); - AudioResampler& operator=(const AudioResampler&); - - int32_t mBitDepth; - int32_t mChannelCount; - int32_t mSampleRate; - int32_t mInSampleRate; - AudioBufferProvider::Buffer mBuffer; - union { - int16_t mVolume[2]; - uint32_t mVolumeRL; - }; - int16_t mTargetVolume[2]; - format mFormat; - size_t mInputIndex; - int32_t mPhaseIncrement; - uint32_t mPhaseFraction; -}; - -// ---------------------------------------------------------------------------- -} -; // namespace android - -#endif // ANDROID_AUDIO_RESAMPLER_H diff --git a/libs/audioflinger/AudioResamplerCubic.cpp b/libs/audioflinger/AudioResamplerCubic.cpp deleted file mode 100644 index 1d247bd..0000000 --- a/libs/audioflinger/AudioResamplerCubic.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <string.h> -#include <sys/types.h> -#include <cutils/log.h> - -#include "AudioResampler.h" -#include "AudioResamplerCubic.h" - -#define LOG_TAG "AudioSRC" - -namespace android { -// ---------------------------------------------------------------------------- - -void AudioResamplerCubic::init() { - memset(&left, 0, sizeof(state)); - memset(&right, 0, sizeof(state)); -} - -void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - // should never happen, but we overflow if it does - // LOG_ASSERT(outFrameCount < 32767); - - // select the appropriate resampler - switch (mChannelCount) { - case 1: - resampleMono16(out, outFrameCount, provider); - break; - case 2: - resampleStereo16(out, outFrameCount, provider); - break; - } -} - -void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - int32_t vl = mVolume[0]; - int32_t vr = mVolume[1]; - - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - // fetch first buffer - if (mBuffer.frameCount == 0) { - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) - return; - // LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); - } - int16_t *in = mBuffer.i16; - - while (outputIndex < outputSampleCount) { - int32_t sample; - int32_t x; - - // calculate output sample - x = phaseFraction >> kPreInterpShift; - out[outputIndex++] += vl * interp(&left, x); - out[outputIndex++] += vr * interp(&right, x); - // out[outputIndex++] += vr * in[inputIndex*2]; - - // increment phase - phaseFraction += phaseIncrement; - uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); - phaseFraction &= kPhaseMask; - - // time to fetch another sample - while (indexIncrement--) { - - inputIndex++; - if (inputIndex == mBuffer.frameCount) { - inputIndex = 0; - provider->releaseBuffer(&mBuffer); - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) - goto save_state; // ugly, but efficient - in = mBuffer.i16; - // LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount); - } - - // advance sample state - advance(&left, in[inputIndex*2]); - advance(&right, in[inputIndex*2+1]); - } - } - -save_state: - // LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - int32_t vl = mVolume[0]; - int32_t vr = mVolume[1]; - - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - // fetch first buffer - if (mBuffer.frameCount == 0) { - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) - return; - // LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount); - } - int16_t *in = mBuffer.i16; - - while (outputIndex < outputSampleCount) { - int32_t sample; - int32_t x; - - // calculate output sample - x = phaseFraction >> kPreInterpShift; - sample = interp(&left, x); - out[outputIndex++] += vl * sample; - out[outputIndex++] += vr * sample; - - // increment phase - phaseFraction += phaseIncrement; - uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); - phaseFraction &= kPhaseMask; - - // time to fetch another sample - while (indexIncrement--) { - - inputIndex++; - if (inputIndex == mBuffer.frameCount) { - inputIndex = 0; - provider->releaseBuffer(&mBuffer); - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) - goto save_state; // ugly, but efficient - // LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); - in = mBuffer.i16; - } - - // advance sample state - advance(&left, in[inputIndex]); - } - } - -save_state: - // LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -// ---------------------------------------------------------------------------- -} -; // namespace android - diff --git a/libs/audioflinger/AudioResamplerCubic.h b/libs/audioflinger/AudioResamplerCubic.h deleted file mode 100644 index b72b62a..0000000 --- a/libs/audioflinger/AudioResamplerCubic.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_AUDIO_RESAMPLER_CUBIC_H -#define ANDROID_AUDIO_RESAMPLER_CUBIC_H - -#include <stdint.h> -#include <sys/types.h> -#include <cutils/log.h> - -#include "AudioResampler.h" - -namespace android { -// ---------------------------------------------------------------------------- - -class AudioResamplerCubic : public AudioResampler { -public: - AudioResamplerCubic(int bitDepth, int inChannelCount, int32_t sampleRate) : - AudioResampler(bitDepth, inChannelCount, sampleRate) { - } - virtual void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); -private: - // number of bits used in interpolation multiply - 14 bits avoids overflow - static const int kNumInterpBits = 14; - - // bits to shift the phase fraction down to avoid overflow - static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits; - typedef struct { - int32_t a, b, c, y0, y1, y2, y3; - } state; - void init(); - void resampleMono16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); - void resampleStereo16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); - static inline int32_t interp(state* p, int32_t x) { - return (((((p->a * x >> 14) + p->b) * x >> 14) + p->c) * x >> 14) + p->y1; - } - static inline void advance(state* p, int16_t in) { - p->y0 = p->y1; - p->y1 = p->y2; - p->y2 = p->y3; - p->y3 = in; - p->a = (3 * (p->y1 - p->y2) - p->y0 + p->y3) >> 1; - p->b = (p->y2 << 1) + p->y0 - (((5 * p->y1 + p->y3)) >> 1); - p->c = (p->y2 - p->y0) >> 1; - } - state left, right; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif /*ANDROID_AUDIO_RESAMPLER_CUBIC_H*/ diff --git a/libs/audioflinger/AudioResamplerSinc.cpp b/libs/audioflinger/AudioResamplerSinc.cpp deleted file mode 100644 index 9e5e254..0000000 --- a/libs/audioflinger/AudioResamplerSinc.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <string.h> -#include "AudioResamplerSinc.h" - -namespace android { -// ---------------------------------------------------------------------------- - - -/* - * These coeficients are computed with the "fir" utility found in - * tools/resampler_tools - * TODO: A good optimization would be to transpose this matrix, to take - * better advantage of the data-cache. - */ -const int32_t AudioResamplerSinc::mFirCoefsUp[] = { - 0x7fffffff, 0x7f15d078, 0x7c5e0da6, 0x77ecd867, 0x71e2e251, 0x6a6c304a, 0x61be7269, 0x58170412, 0x4db8ab05, 0x42e92ea6, 0x37eee214, 0x2d0e3bb1, 0x22879366, 0x18951e95, 0x0f693d0d, 0x072d2621, - 0x00000000, 0xf9f66655, 0xf51a5fd7, 0xf16bbd84, 0xeee0d9ac, 0xed67a922, 0xece70de6, 0xed405897, 0xee50e505, 0xeff3be30, 0xf203370f, 0xf45a6741, 0xf6d67d53, 0xf957db66, 0xfbc2f647, 0xfe00f2b9, - 0x00000000, 0x01b37218, 0x0313a0c6, 0x041d930d, 0x04d28057, 0x053731b0, 0x05534dff, 0x05309bfd, 0x04da440d, 0x045c1aee, 0x03c1fcdd, 0x03173ef5, 0x02663ae8, 0x01b7f736, 0x0113ec79, 0x007fe6a9, - 0x00000000, 0xff96b229, 0xff44f99f, 0xff0a86be, 0xfee5f803, 0xfed518fd, 0xfed521fd, 0xfee2f4fd, 0xfefb54f8, 0xff1b159b, 0xff3f4203, 0xff6539e0, 0xff8ac502, 0xffae1ddd, 0xffcdf3f9, 0xffe96798, - 0x00000000, 0x00119de6, 0x001e6b7e, 0x0026cb7a, 0x002b4830, 0x002c83d6, 0x002b2a82, 0x0027e67a, 0x002356f9, 0x001e098e, 0x001875e4, 0x0012fbbe, 0x000de2d1, 0x00095c10, 0x00058414, 0x00026636, - 0x00000000, 0xfffe44a9, 0xfffd206d, 0xfffc7b7f, 0xfffc3c8f, 0xfffc4ac2, 0xfffc8f2b, 0xfffcf5c4, 0xfffd6df3, 0xfffdeab2, 0xfffe6275, 0xfffececf, 0xffff2c07, 0xffff788c, 0xffffb471, 0xffffe0f2, - 0x00000000, 0x000013e6, 0x00001f03, 0x00002396, 0x00002399, 0x000020b6, 0x00001c3c, 0x00001722, 0x00001216, 0x00000d81, 0x0000099c, 0x0000067c, 0x00000419, 0x0000025f, 0x00000131, 0x00000070, - 0x00000000, 0xffffffc7, 0xffffffb3, 0xffffffb3, 0xffffffbe, 0xffffffcd, 0xffffffdb, 0xffffffe7, 0xfffffff0, 0xfffffff7, 0xfffffffb, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000 // this one is needed for lerping the last coefficient -}; - -/* - * These coefficients are optimized for 48KHz -> 44.1KHz (stop-band at 22.050KHz) - * It's possible to use the above coefficient for any down-sampling - * at the expense of a slower processing loop (we can interpolate - * these coefficient from the above by "Stretching" them in time). - */ -const int32_t AudioResamplerSinc::mFirCoefsDown[] = { - 0x7fffffff, 0x7f55e46d, 0x7d5b4c60, 0x7a1b4b98, 0x75a7fb14, 0x7019f0bd, 0x698f875a, 0x622bfd59, 0x5a167256, 0x5178cc54, 0x487e8e6c, 0x3f53aae8, 0x36235ad4, 0x2d17047b, 0x245539ab, 0x1c00d540, - 0x14383e57, 0x0d14d5ca, 0x06aa910b, 0x0107c38b, 0xfc351654, 0xf835abae, 0xf5076b45, 0xf2a37202, 0xf0fe9faa, 0xf00a3bbd, 0xefb4aa81, 0xefea2b05, 0xf0959716, 0xf1a11e83, 0xf2f6f7a0, 0xf481fff4, - 0xf62e48ce, 0xf7e98ca5, 0xf9a38b4c, 0xfb4e4bfa, 0xfcde456f, 0xfe4a6d30, 0xff8c2fdf, 0x009f5555, 0x0181d393, 0x0233940f, 0x02b62f06, 0x030ca07d, 0x033afa62, 0x03461725, 0x03334f83, 0x030835fa, - 0x02ca59cc, 0x027f12d1, 0x022b570d, 0x01d39a49, 0x017bb78f, 0x0126e414, 0x00d7aaaf, 0x008feec7, 0x0050f584, 0x001b73e3, 0xffefa063, 0xffcd46ed, 0xffb3ddcd, 0xffa29aaa, 0xff988691, 0xff949066, - 0xff959d24, 0xff9a959e, 0xffa27195, 0xffac4011, 0xffb72d2b, 0xffc28569, 0xffcdb706, 0xffd85171, 0xffe20364, 0xffea97e9, 0xfff1f2b2, 0xfff80c06, 0xfffcec92, 0x0000a955, 0x00035fd8, 0x000532cf, - 0x00064735, 0x0006c1f9, 0x0006c62d, 0x000673ba, 0x0005e68f, 0x00053630, 0x000475a3, 0x0003b397, 0x0002fac1, 0x00025257, 0x0001be9e, 0x0001417a, 0x0000dafd, 0x000089eb, 0x00004c28, 0x00001f1d, - 0x00000000, 0xffffec10, 0xffffe0be, 0xffffdbc5, 0xffffdb39, 0xffffdd8b, 0xffffe182, 0xffffe638, 0xffffeb0a, 0xffffef8f, 0xfffff38b, 0xfffff6e3, 0xfffff993, 0xfffffba6, 0xfffffd30, 0xfffffe4a, - 0xffffff09, 0xffffff85, 0xffffffd1, 0xfffffffb, 0x0000000f, 0x00000016, 0x00000015, 0x00000012, 0x0000000d, 0x00000009, 0x00000006, 0x00000003, 0x00000002, 0x00000001, 0x00000000, 0x00000000, - 0x00000000 // this one is needed for lerping the last coefficient -}; - -// ---------------------------------------------------------------------------- - -static inline -int32_t mulRL(int left, int32_t in, uint32_t vRL) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - if (left) { - asm( "smultb %[out], %[in], %[vRL] \n" - : [out]"=r"(out) - : [in]"%r"(in), [vRL]"r"(vRL) - : ); - } else { - asm( "smultt %[out], %[in], %[vRL] \n" - : [out]"=r"(out) - : [in]"%r"(in), [vRL]"r"(vRL) - : ); - } - return out; -#else - if (left) { - return int16_t(in>>16) * int16_t(vRL&0xFFFF); - } else { - return int16_t(in>>16) * int16_t(vRL>>16); - } -#endif -} - -static inline -int32_t mulAdd(int16_t in, int32_t v, int32_t a) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - asm( "smlawb %[out], %[v], %[in], %[a] \n" - : [out]"=r"(out) - : [in]"%r"(in), [v]"r"(v), [a]"r"(a) - : ); - return out; -#else - return a + in * (v>>16); - // improved precision - // return a + in * (v>>16) + ((in * (v & 0xffff)) >> 16); -#endif -} - -static inline -int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - if (left) { - asm( "smlawb %[out], %[v], %[inRL], %[a] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) - : ); - } else { - asm( "smlawt %[out], %[v], %[inRL], %[a] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) - : ); - } - return out; -#else - if (left) { - return a + (int16_t(inRL&0xFFFF) * (v>>16)); - //improved precision - // return a + (int16_t(inRL&0xFFFF) * (v>>16)) + ((int16_t(inRL&0xFFFF) * (v & 0xffff)) >> 16); - } else { - return a + (int16_t(inRL>>16) * (v>>16)); - } -#endif -} - -// ---------------------------------------------------------------------------- - -AudioResamplerSinc::AudioResamplerSinc(int bitDepth, - int inChannelCount, int32_t sampleRate) - : AudioResampler(bitDepth, inChannelCount, sampleRate), - mState(0) -{ - /* - * Layout of the state buffer for 32 tap: - * - * "present" sample beginning of 2nd buffer - * v v - * 0 01 2 23 3 - * 0 F0 0 F0 F - * [pppppppppppppppInnnnnnnnnnnnnnnnpppppppppppppppInnnnnnnnnnnnnnnn] - * ^ ^ head - * - * p = past samples, convoluted with the (p)ositive side of sinc() - * n = future samples, convoluted with the (n)egative side of sinc() - * r = extra space for implementing the ring buffer - * - */ - - const size_t numCoefs = 2*halfNumCoefs; - const size_t stateSize = numCoefs * inChannelCount * 2; - mState = new int16_t[stateSize]; - memset(mState, 0, sizeof(int16_t)*stateSize); - mImpulse = mState + (halfNumCoefs-1)*inChannelCount; - mRingFull = mImpulse + (numCoefs+1)*inChannelCount; -} - -AudioResamplerSinc::~AudioResamplerSinc() -{ - delete [] mState; -} - -void AudioResamplerSinc::init() { -} - -void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) -{ - mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown; - - // select the appropriate resampler - switch (mChannelCount) { - case 1: - resample<1>(out, outFrameCount, provider); - break; - case 2: - resample<2>(out, outFrameCount, provider); - break; - } -} - - -template<int CHANNELS> -void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) -{ - int16_t* impulse = mImpulse; - uint32_t vRL = mVolumeRL; - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - AudioBufferProvider::Buffer& buffer(mBuffer); - while (outputIndex < outputSampleCount) { - // buffer is empty, fetch a new one - while (buffer.frameCount == 0) { - buffer.frameCount = inFrameCount; - provider->getNextBuffer(&buffer); - if (buffer.raw == NULL) { - goto resample_exit; - } - const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; - if (phaseIndex == 1) { - // read one frame - read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); - } else if (phaseIndex == 2) { - // read 2 frames - read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); - inputIndex++; - if (inputIndex >= mBuffer.frameCount) { - inputIndex -= mBuffer.frameCount; - provider->releaseBuffer(&buffer); - } else { - read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); - } - } - } - int16_t *in = buffer.i16; - const size_t frameCount = buffer.frameCount; - - // Always read-in the first samples from the input buffer - int16_t* head = impulse + halfNumCoefs*CHANNELS; - head[0] = in[inputIndex*CHANNELS + 0]; - if (CHANNELS == 2) - head[1] = in[inputIndex*CHANNELS + 1]; - - // handle boundary case - int32_t l, r; - while (outputIndex < outputSampleCount) { - filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse); - out[outputIndex++] += 2 * mulRL(1, l, vRL); - out[outputIndex++] += 2 * mulRL(0, r, vRL); - - phaseFraction += phaseIncrement; - const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; - if (phaseIndex == 1) { - inputIndex++; - if (inputIndex >= frameCount) - break; // need a new buffer - read<CHANNELS>(impulse, phaseFraction, in, inputIndex); - } else if(phaseIndex == 2) { // maximum value - inputIndex++; - if (inputIndex >= frameCount) - break; // 0 frame available, 2 frames needed - // read first frame - read<CHANNELS>(impulse, phaseFraction, in, inputIndex); - inputIndex++; - if (inputIndex >= frameCount) - break; // 0 frame available, 1 frame needed - // read second frame - read<CHANNELS>(impulse, phaseFraction, in, inputIndex); - } - } - - // if done with buffer, save samples - if (inputIndex >= frameCount) { - inputIndex -= frameCount; - provider->releaseBuffer(&buffer); - } - } - -resample_exit: - mImpulse = impulse; - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -template<int CHANNELS> -/*** -* read() -* -* This function reads only one frame from input buffer and writes it in -* state buffer -* -**/ -void AudioResamplerSinc::read( - int16_t*& impulse, uint32_t& phaseFraction, - int16_t const* in, size_t inputIndex) -{ - const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; - impulse += CHANNELS; - phaseFraction -= 1LU<<kNumPhaseBits; - if (impulse >= mRingFull) { - const size_t stateSize = (halfNumCoefs*2)*CHANNELS; - memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize); - impulse -= stateSize; - } - int16_t* head = impulse + halfNumCoefs*CHANNELS; - head[0] = in[inputIndex*CHANNELS + 0]; - if (CHANNELS == 2) - head[1] = in[inputIndex*CHANNELS + 1]; -} - -template<int CHANNELS> -void AudioResamplerSinc::filterCoefficient( - int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples) -{ - // compute the index of the coefficient on the positive side and - // negative side - uint32_t indexP = (phase & cMask) >> cShift; - uint16_t lerpP = (phase & pMask) >> pShift; - uint32_t indexN = (-phase & cMask) >> cShift; - uint16_t lerpN = (-phase & pMask) >> pShift; - if ((indexP == 0) && (lerpP == 0)) { - indexN = cMask >> cShift; - lerpN = pMask >> pShift; - } - - l = 0; - r = 0; - int32_t const* coefs = mFirCoefs; - int16_t const *sP = samples; - int16_t const *sN = samples+CHANNELS; - for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) { - interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); - interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; - interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); - interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; - interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); - interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; - interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); - interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; - } -} - -template<int CHANNELS> -void AudioResamplerSinc::interpolate( - int32_t& l, int32_t& r, - int32_t const* coefs, int16_t lerp, int16_t const* samples) -{ - int32_t c0 = coefs[0]; - int32_t c1 = coefs[1]; - int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0); - if (CHANNELS == 2) { - uint32_t rl = *reinterpret_cast<uint32_t const*>(samples); - l = mulAddRL(1, rl, sinc, l); - r = mulAddRL(0, rl, sinc, r); - } else { - r = l = mulAdd(samples[0], sinc, l); - } -} - -// ---------------------------------------------------------------------------- -}; // namespace android - diff --git a/libs/audioflinger/AudioResamplerSinc.h b/libs/audioflinger/AudioResamplerSinc.h deleted file mode 100644 index e6cb90b..0000000 --- a/libs/audioflinger/AudioResamplerSinc.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_AUDIO_RESAMPLER_SINC_H -#define ANDROID_AUDIO_RESAMPLER_SINC_H - -#include <stdint.h> -#include <sys/types.h> -#include <cutils/log.h> - -#include "AudioResampler.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -class AudioResamplerSinc : public AudioResampler { -public: - AudioResamplerSinc(int bitDepth, int inChannelCount, int32_t sampleRate); - - ~AudioResamplerSinc(); - - virtual void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); -private: - void init(); - - template<int CHANNELS> - void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); - - template<int CHANNELS> - inline void filterCoefficient( - int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples); - - template<int CHANNELS> - inline void interpolate( - int32_t& l, int32_t& r, - int32_t const* coefs, int16_t lerp, int16_t const* samples); - - template<int CHANNELS> - inline void read(int16_t*& impulse, uint32_t& phaseFraction, - int16_t const* in, size_t inputIndex); - - int16_t *mState; - int16_t *mImpulse; - int16_t *mRingFull; - - int32_t const * mFirCoefs; - static const int32_t mFirCoefsDown[]; - static const int32_t mFirCoefsUp[]; - - // ---------------------------------------------------------------------------- - static const int32_t RESAMPLE_FIR_NUM_COEF = 8; - static const int32_t RESAMPLE_FIR_LERP_INT_BITS = 4; - - // we have 16 coefs samples per zero-crossing - static const int coefsBits = RESAMPLE_FIR_LERP_INT_BITS; // 4 - static const int cShift = kNumPhaseBits - coefsBits; // 26 - static const uint32_t cMask = ((1<<coefsBits)-1) << cShift; // 0xf<<26 = 3c00 0000 - - // and we use 15 bits to interpolate between these samples - // this cannot change because the mul below rely on it. - static const int pLerpBits = 15; - static const int pShift = kNumPhaseBits - coefsBits - pLerpBits; // 11 - static const uint32_t pMask = ((1<<pLerpBits)-1) << pShift; // 0x7fff << 11 - - // number of zero-crossing on each side - static const unsigned int halfNumCoefs = RESAMPLE_FIR_NUM_COEF; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif /*ANDROID_AUDIO_RESAMPLER_SINC_H*/ diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk deleted file mode 100644 index 496e271..0000000 --- a/libs/surfaceflinger/Android.mk +++ /dev/null @@ -1,49 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - clz.cpp.arm \ - DisplayHardware/DisplayHardware.cpp \ - DisplayHardware/DisplayHardwareBase.cpp \ - GPUHardware/GPUHardware.cpp \ - BootAnimation.cpp \ - BlurFilter.cpp.arm \ - CPUGauge.cpp \ - Layer.cpp \ - LayerBase.cpp \ - LayerBuffer.cpp \ - LayerBlur.cpp \ - LayerBitmap.cpp \ - LayerDim.cpp \ - LayerOrientationAnim.cpp \ - OrientationAnimation.cpp \ - SurfaceFlinger.cpp \ - Tokenizer.cpp \ - Transform.cpp \ - VRamHeap.cpp - - -# need "-lrt" on Linux simulator to pick up clock_gettime -ifeq ($(TARGET_SIMULATOR),true) - ifeq ($(HOST_OS),linux) - LOCAL_LDLIBS += -lrt - endif -endif - -LOCAL_SHARED_LIBRARIES := \ - libhardware \ - libutils \ - libcutils \ - libui \ - libcorecg \ - libsgl \ - libpixelflinger \ - libEGL \ - libGLESv1_CM - -LOCAL_C_INCLUDES := \ - $(call include-path-for, corecg graphics) - -LOCAL_MODULE:= libsurfaceflinger - -include $(BUILD_SHARED_LIBRARY) diff --git a/libs/surfaceflinger/Barrier.h b/libs/surfaceflinger/Barrier.h deleted file mode 100644 index e2bcf6a..0000000 --- a/libs/surfaceflinger/Barrier.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_BARRIER_H -#define ANDROID_BARRIER_H - -#include <stdint.h> -#include <sys/types.h> -#include <utils/threads.h> - -namespace android { - -class Barrier -{ -public: - inline Barrier() : state(CLOSED) { } - inline ~Barrier() { } - void open() { - // gcc memory barrier, this makes sure all memory writes - // have been issued by gcc. On an SMP system we'd need a real - // h/w barrier. - asm volatile ("":::"memory"); - Mutex::Autolock _l(lock); - state = OPENED; - cv.broadcast(); - } - void close() { - Mutex::Autolock _l(lock); - state = CLOSED; - } - void wait() const { - Mutex::Autolock _l(lock); - while (state == CLOSED) { - cv.wait(lock); - } - } -private: - enum { OPENED, CLOSED }; - mutable Mutex lock; - mutable Condition cv; - volatile int state; -}; - -}; // namespace android - -#endif // ANDROID_BARRIER_H diff --git a/libs/surfaceflinger/BlurFilter.cpp b/libs/surfaceflinger/BlurFilter.cpp deleted file mode 100644 index 5dc0ba0..0000000 --- a/libs/surfaceflinger/BlurFilter.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdint.h> -#include <utils/Errors.h> - -#include <pixelflinger/pixelflinger.h> - -#include "clz.h" - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -namespace android { - -#if BYTE_ORDER == LITTLE_ENDIAN -inline uint32_t BLUR_RGBA_TO_HOST(uint32_t v) { - return v; -} -inline uint32_t BLUR_HOST_TO_RGBA(uint32_t v) { - return v; -} -#else -inline uint32_t BLUR_RGBA_TO_HOST(uint32_t v) { - return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00); -} -inline uint32_t BLUR_HOST_TO_RGBA(uint32_t v) { - return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00); -} -#endif - -const int BLUR_DITHER_BITS = 6; // dither weights stored on 6 bits -const int BLUR_DITHER_ORDER_SHIFT= 3; -const int BLUR_DITHER_ORDER = (1<<BLUR_DITHER_ORDER_SHIFT); -const int BLUR_DITHER_SIZE = BLUR_DITHER_ORDER * BLUR_DITHER_ORDER; -const int BLUR_DITHER_MASK = BLUR_DITHER_ORDER-1; - -static const uint8_t gDitherMatrix[BLUR_DITHER_SIZE] = { - 0, 32, 8, 40, 2, 34, 10, 42, - 48, 16, 56, 24, 50, 18, 58, 26, - 12, 44, 4, 36, 14, 46, 6, 38, - 60, 28, 52, 20, 62, 30, 54, 22, - 3, 35, 11, 43, 1, 33, 9, 41, - 51, 19, 59, 27, 49, 17, 57, 25, - 15, 47, 7, 39, 13, 45, 5, 37, - 63, 31, 55, 23, 61, 29, 53, 21 -}; - - -template <int FACTOR = 0> -struct BlurColor565 -{ - typedef uint16_t type; - int r, g, b; - inline BlurColor565() { } - inline BlurColor565(uint16_t v) { - r = v >> 11; - g = (v >> 5) & 0x3E; - b = v & 0x1F; - } - inline void clear() { r=g=b=0; } - inline uint16_t to(int shift, int last, int dither) const { - int R = r; - int G = g; - int B = b; - if (UNLIKELY(last)) { - if (FACTOR>0) { - int L = (R+G+B)>>1; - R += (((L>>1) - R) * FACTOR) >> 8; - G += (((L ) - G) * FACTOR) >> 8; - B += (((L>>1) - B) * FACTOR) >> 8; - } - R += (dither << shift) >> BLUR_DITHER_BITS; - G += (dither << shift) >> BLUR_DITHER_BITS; - B += (dither << shift) >> BLUR_DITHER_BITS; - } - R >>= shift; - G >>= shift; - B >>= shift; - return (R<<11) | (G<<5) | B; - } - inline BlurColor565& operator += (const BlurColor565& rhs) { - r += rhs.r; - g += rhs.g; - b += rhs.b; - return *this; - } - inline BlurColor565& operator -= (const BlurColor565& rhs) { - r -= rhs.r; - g -= rhs.g; - b -= rhs.b; - return *this; - } -}; - -struct BlurGray565 -{ - typedef uint16_t type; - int l; - inline BlurGray565() { } - inline BlurGray565(uint16_t v) { - int r = v >> 11; - int g = (v >> 5) & 0x3F; - int b = v & 0x1F; - l = (r + g + b + 1)>>1; - } - inline void clear() { l=0; } - inline uint16_t to(int shift, int last, int dither) const { - int L = l; - if (UNLIKELY(last)) { - L += (dither << shift) >> BLUR_DITHER_BITS; - } - L >>= shift; - return ((L>>1)<<11) | (L<<5) | (L>>1); - } - inline BlurGray565& operator += (const BlurGray565& rhs) { - l += rhs.l; - return *this; - } - inline BlurGray565& operator -= (const BlurGray565& rhs) { - l -= rhs.l; - return *this; - } -}; - -struct BlurGray8888 -{ - typedef uint32_t type; - int l, a; - inline BlurGray8888() { } - inline BlurGray8888(uint32_t v) { - v = BLUR_RGBA_TO_HOST(v); - int r = v & 0xFF; - int g = (v >> 8) & 0xFF; - int b = (v >> 16) & 0xFF; - a = v >> 24; - l = r + g + g + b; - } - inline void clear() { l=a=0; } - inline uint32_t to(int shift, int last, int dither) const { - int L = l; - int A = a; - if (UNLIKELY(last)) { - L += (dither << (shift+2)) >> BLUR_DITHER_BITS; - A += (dither << shift) >> BLUR_DITHER_BITS; - } - L >>= (shift+2); - A >>= shift; - return BLUR_HOST_TO_RGBA((A<<24) | (L<<16) | (L<<8) | L); - } - inline BlurGray8888& operator += (const BlurGray8888& rhs) { - l += rhs.l; - a += rhs.a; - return *this; - } - inline BlurGray8888& operator -= (const BlurGray8888& rhs) { - l -= rhs.l; - a -= rhs.a; - return *this; - } -}; - - -template<typename PIXEL> -static status_t blurFilter( - GGLSurface const* dst, - GGLSurface const* src, - int kernelSizeUser, - int repeat) -{ - typedef typename PIXEL::type TYPE; - - const int shift = 31 - clz(kernelSizeUser); - const int areaShift = shift*2; - const int kernelSize = 1<<shift; - const int kernelHalfSize = kernelSize/2; - const int mask = kernelSize-1; - const int w = src->width; - const int h = src->height; - const uint8_t* ditherMatrix = gDitherMatrix; - - // we need a temporary buffer to store one line of blurred columns - // as well as kernelSize lines of source pixels organized as a ring buffer. - void* const temporary_buffer = malloc( - (w + kernelSize) * sizeof(PIXEL) + - (src->stride * kernelSize) * sizeof(TYPE)); - if (!temporary_buffer) - return NO_MEMORY; - - PIXEL* const sums = (PIXEL*)temporary_buffer; - TYPE* const scratch = (TYPE*)(sums + w + kernelSize); - - // Apply the blur 'repeat' times, this is used to approximate - // gaussian blurs. 3 times gives good results. - for (int k=0 ; k<repeat ; k++) { - - // Clear the columns sums for this round - memset(sums, 0, (w + kernelSize) * sizeof(PIXEL)); - TYPE* head; - TYPE pixel; - PIXEL current; - - // Since we're going to override the source data we need - // to copy it in a temporary buffer. Only kernelSize lines are - // required. But since we start in the center of the kernel, - // we only copy half of the data, and fill the rest with zeros - // (assuming black/transparent pixels). - memcpy( scratch + src->stride*kernelHalfSize, - src->data, - src->stride*kernelHalfSize*sizeof(TYPE)); - - // sum half of each column, because we assume the first half is - // zeros (black/transparent). - for (int y=0 ; y<kernelHalfSize ; y++) { - head = (TYPE*)src->data + y*src->stride; - for (int x=0 ; x<w ; x++) - sums[x] += PIXEL( *head++ ); - } - - for (int y=0 ; y<h ; y++) { - TYPE* fb = (TYPE*)dst->data + y*dst->stride; - - // compute the dither matrix line - uint8_t const * ditherY = ditherMatrix - + (y & BLUR_DITHER_MASK)*BLUR_DITHER_ORDER; - - // Horizontal blur pass on the columns sums - int count, dither, x=0; - PIXEL const * out= sums; - PIXEL const * in = sums; - current.clear(); - - count = kernelHalfSize; - do { - current += *in; - in++; - } while (--count); - - count = kernelHalfSize; - do { - current += *in; - dither = *(ditherY + ((x++)&BLUR_DITHER_MASK)); - *fb++ = current.to(areaShift, k==repeat-1, dither); - in++; - } while (--count); - - count = w-kernelSize; - do { - current += *in; - current -= *out; - dither = *(ditherY + ((x++)&BLUR_DITHER_MASK)); - *fb++ = current.to(areaShift, k==repeat-1, dither); - in++, out++; - } while (--count); - - count = kernelHalfSize; - do { - current -= *out; - dither = *(ditherY + ((x++)&BLUR_DITHER_MASK)); - *fb++ = current.to(areaShift, k==repeat-1, dither); - out++; - } while (--count); - - // vertical blur pass, subtract the oldest line from each columns - // and add a new line. Subtract or add zeros at the top - // and bottom edges. - TYPE* const tail = scratch + (y & mask) * src->stride; - if (y >= kernelHalfSize) { - for (int x=0 ; x<w ; x++) - sums[x] -= PIXEL( tail[x] ); - } - if (y < h-kernelSize) { - memcpy( tail, - (TYPE*)src->data + (y+kernelHalfSize)*src->stride, - src->stride*sizeof(TYPE)); - for (int x=0 ; x<w ; x++) - sums[x] += PIXEL( tail[x] ); - } - } - - // The subsequent passes are always done in-place. - src = dst; - } - - free(temporary_buffer); - - return NO_ERROR; -} - -template status_t blurFilter< BlurColor565<0x80> >( - GGLSurface const* dst, - GGLSurface const* src, - int kernelSizeUser, - int repeat); - -status_t blurFilter( - GGLSurface const* image, - int kernelSizeUser, - int repeat) -{ - return blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat); -} - -} // namespace android - -//err = blur< BlurColor565<0x80> >(dst, src, kernelSizeUser, repeat); -//err = blur<BlurGray565>(dst, src, kernelSizeUser, repeat); -//err = blur<BlurGray8888>(dst, src, kernelSizeUser, repeat); diff --git a/libs/surfaceflinger/BlurFilter.h b/libs/surfaceflinger/BlurFilter.h deleted file mode 100644 index 294db43..0000000 --- a/libs/surfaceflinger/BlurFilter.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef ANDROID_BLUR_FILTER_H -#define ANDROID_BLUR_FILTER_H - -#include <stdint.h> -#include <utils/Errors.h> - -#include <pixelflinger/pixelflinger.h> - -namespace android { - -status_t blurFilter( - GGLSurface const* image, - int kernelSizeUser, - int repeat); - -} // namespace android - -#endif // ANDROID_BLUR_FILTER_H diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp deleted file mode 100644 index 2b30336..0000000 --- a/libs/surfaceflinger/BootAnimation.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "BootAnimation" - -#include <stdint.h> -#include <sys/types.h> -#include <math.h> -#include <fcntl.h> -#include <utils/misc.h> - -#include <utils/threads.h> -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/Log.h> -#include <utils/AssetManager.h> - -#include <ui/PixelFormat.h> -#include <ui/Rect.h> -#include <ui/Region.h> -#include <ui/DisplayInfo.h> -#include <ui/ISurfaceComposer.h> -#include <ui/ISurfaceFlingerClient.h> -#include <ui/EGLNativeWindowSurface.h> - -#include <core/SkBitmap.h> -#include <images/SkImageDecoder.h> - -#include <GLES/gl.h> -#include <GLES/glext.h> -#include <EGL/eglext.h> - -#include "BootAnimation.h" - -namespace android { - -// --------------------------------------------------------------------------- - -BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) : - Thread(false) { - mSession = SurfaceComposerClient::clientForConnection( - composer->createConnection()->asBinder()); -} - -BootAnimation::~BootAnimation() { -} - -void BootAnimation::onFirstRef() { - run("BootAnimation", PRIORITY_DISPLAY); -} - -const sp<SurfaceComposerClient>& BootAnimation::session() const { - return mSession; -} - -status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, - const char* name) { - Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); - if (!asset) - return NO_INIT; - SkBitmap bitmap; - SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(), - &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode); - asset->close(); - delete asset; - - // ensure we can call getPixels(). No need to call unlock, since the - // bitmap will go out of scope when we return from this method. - bitmap.lockPixels(); - - const int w = bitmap.width(); - const int h = bitmap.height(); - const void* p = bitmap.getPixels(); - - GLint crop[4] = { 0, h, w, -h }; - texture->w = w; - texture->h = h; - - glGenTextures(1, &texture->name); - glBindTexture(GL_TEXTURE_2D, texture->name); - - switch (bitmap.getConfig()) { - case SkBitmap::kA8_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, - GL_UNSIGNED_BYTE, p); - break; - case SkBitmap::kARGB_4444_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, - GL_UNSIGNED_SHORT_4_4_4_4, p); - break; - case SkBitmap::kARGB_8888_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, - GL_UNSIGNED_BYTE, p); - break; - case SkBitmap::kRGB_565_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, - GL_UNSIGNED_SHORT_5_6_5, p); - break; - default: - break; - } - - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - return NO_ERROR; -} - -status_t BootAnimation::readyToRun() { - mAssets.addDefaultAssets(); - - DisplayInfo dinfo; - status_t status = session()->getDisplayInfo(0, &dinfo); - if (status) - return -1; - - // create the native surface - sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h, - PIXEL_FORMAT_RGB_565); - session()->openTransaction(); - s->setLayer(0x40000000); - session()->closeTransaction(); - - // initialize opengl and egl - const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 0, EGL_NONE }; - EGLint w, h, dummy; - EGLint numConfigs; - EGLConfig config; - EGLSurface surface; - EGLContext context; - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglChooseConfig(display, attribs, &config, 1, &numConfigs); - - mNativeWindowSurface = new EGLNativeWindowSurface(s); - surface = eglCreateWindowSurface(display, config, - mNativeWindowSurface.get(), NULL); - - context = eglCreateContext(display, config, NULL, NULL); - eglQuerySurface(display, surface, EGL_WIDTH, &w); - eglQuerySurface(display, surface, EGL_HEIGHT, &h); - eglMakeCurrent(display, surface, surface, context); - mDisplay = display; - mContext = context; - mSurface = surface; - mWidth = w; - mHeight = h; - mFlingerSurface = s; - - // initialize GL - glShadeModel(GL_FLAT); - glEnable(GL_DITHER); - glEnable(GL_TEXTURE_2D); - glEnable(GL_SCISSOR_TEST); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - return NO_ERROR; -} - -void BootAnimation::requestExit() { - mBarrier.open(); - Thread::requestExit(); -} - -bool BootAnimation::threadLoop() { - bool r = android(); - eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(mDisplay, mContext); - eglDestroySurface(mDisplay, mSurface); - mNativeWindowSurface.clear(); - return r; -} - -bool BootAnimation::android() { - initTexture(&mAndroid[0], mAssets, "images/android_320x480.png"); - initTexture(&mAndroid[1], mAssets, "images/boot_robot.png"); - initTexture(&mAndroid[2], mAssets, "images/boot_robot_glow.png"); - - // erase screen - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); - - // clear screen - glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(mDisplay, mSurface); - - // wait ~1s - usleep(800000); - - // fade in - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - const int steps = 8; - for (int i = 1; i < steps; i++) { - float fade = i / float(steps); - glColor4f(1, 1, 1, fade * fade); - glClear(GL_COLOR_BUFFER_BIT); - glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h); - eglSwapBuffers(mDisplay, mSurface); - } - - // draw last frame - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDisable(GL_BLEND); - glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h); - eglSwapBuffers(mDisplay, mSurface); - - // update rect for the robot - const int x = mWidth - mAndroid[1].w - 33; - const int y = (mHeight - mAndroid[1].h) / 2 - 1; - const Rect updateRect(x, y, x + mAndroid[1].w, y + mAndroid[1].h); - - // draw and update only what we need - mNativeWindowSurface->setSwapRectangle(updateRect.left, - updateRect.top, updateRect.width(), updateRect.height()); - - glEnable(GL_SCISSOR_TEST); - glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), - updateRect.height()); - - const nsecs_t startTime = systemTime(); - do { - // glow speed and shape - nsecs_t time = systemTime() - startTime; - float t = ((4.0f / (360.0f * us2ns(16667))) * time); - t = t - floorf(t); - const float fade = 0.5f + 0.5f * sinf(t * 2 * M_PI); - - // fade the glow in and out - glDisable(GL_BLEND); - glBindTexture(GL_TEXTURE_2D, mAndroid[2].name); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glColor4f(fade, fade, fade, fade); - glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0, - updateRect.width(), updateRect.height()); - - // draw the robot - glEnable(GL_BLEND); - glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0, - updateRect.width(), updateRect.height()); - - // make sure sleep a lot to not take too much CPU away from - // the boot process. With this "glow" animation there is no - // visible difference. - usleep(16667 * 4); - - eglSwapBuffers(mDisplay, mSurface); - } while (!exitPending()); - - glDeleteTextures(1, &mAndroid[0].name); - glDeleteTextures(1, &mAndroid[1].name); - glDeleteTextures(1, &mAndroid[2].name); - return false; -} - -bool BootAnimation::cylon() { - // initialize the textures... - initTexture(&mLeftTrail, mAssets, "images/cylon_left.png"); - initTexture(&mRightTrail, mAssets, "images/cylon_right.png"); - initTexture(&mBrightSpot, mAssets, "images/cylon_dot.png"); - - int w = mWidth; - int h = mHeight; - - const Point c(w / 2, h / 2); - const GLint amplitude = 60; - const int scx = c.x - amplitude - mBrightSpot.w / 2; - const int scy = c.y - mBrightSpot.h / 2; - const int scw = amplitude * 2 + mBrightSpot.w; - const int sch = mBrightSpot.h; - const Rect updateRect(scx, h - scy - sch, scx + scw, h - scy); - - // erase screen - glDisable(GL_SCISSOR_TEST); - glClear(GL_COLOR_BUFFER_BIT); - - eglSwapBuffers(mDisplay, mSurface); - - glClear(GL_COLOR_BUFFER_BIT); - - mNativeWindowSurface->setSwapRectangle(updateRect.left, - updateRect.top, updateRect.width(), updateRect.height()); - - glEnable(GL_SCISSOR_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - // clear the screen to white - Point p; - float t = 0; - float alpha = 1.0f; - const nsecs_t startTime = systemTime(); - nsecs_t fadeTime = 0; - - do { - // Set scissor in interesting area - glScissor(scx, scy, scw, sch); - - // erase screen - glClear(GL_COLOR_BUFFER_BIT); - - // compute wave - const float a = (t * 2 * M_PI) - M_PI / 2; - const float sn = sinf(a); - const float cs = cosf(a); - GLint x = GLint(amplitude * sn); - float derivative = cs; - - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - if (derivative > 0) { - // vanishing trail... - p.x = (-amplitude + c.x) - mBrightSpot.w / 2; - p.y = c.y - mLeftTrail.h / 2; - float fade = 2.0f * (0.5f - t); - //fade *= fade; - glColor4f(fade, fade, fade, fade); - glBindTexture(GL_TEXTURE_2D, mLeftTrail.name); - glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h); - - // trail... - p.x = (x + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16; - p.y = c.y - mRightTrail.h / 2; - fade = t < 0.25f ? t * 4.0f : 1.0f; - fade *= fade; - glColor4f(fade, fade, fade, fade); - glBindTexture(GL_TEXTURE_2D, mRightTrail.name); - glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h); - } else { - // vanishing trail.. - p.x = (amplitude + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16; - p.y = c.y - mRightTrail.h / 2; - float fade = 2.0f * (0.5f - (t - 0.5f)); - //fade *= fade; - glColor4f(fade, fade, fade, fade); - glBindTexture(GL_TEXTURE_2D, mRightTrail.name); - glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h); - - // trail... - p.x = (x + c.x) - mBrightSpot.w / 2; - p.y = c.y - mLeftTrail.h / 2; - fade = t < 0.5f + 0.25f ? (t - 0.5f) * 4.0f : 1.0f; - fade *= fade; - glColor4f(fade, fade, fade, fade); - glBindTexture(GL_TEXTURE_2D, mLeftTrail.name); - glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h); - } - - const Point p(x + c.x - mBrightSpot.w / 2, c.y - mBrightSpot.h / 2); - glBindTexture(GL_TEXTURE_2D, mBrightSpot.name); - glColor4f(1, 0.5, 0.5, 1); - glDrawTexiOES(p.x, p.y, 0, mBrightSpot.w, mBrightSpot.h); - - // update animation - nsecs_t time = systemTime() - startTime; - t = ((4.0f / (360.0f * us2ns(16667))) * time); - t = t - floorf(t); - - eglSwapBuffers(mDisplay, mSurface); - - if (exitPending()) { - if (fadeTime == 0) { - fadeTime = time; - } - time -= fadeTime; - alpha = 1.0f - ((float(time) * 6.0f) / float(s2ns(1))); - - session()->openTransaction(); - mFlingerSurface->setAlpha(alpha * alpha); - session()->closeTransaction(); - } - } while (alpha > 0); - - // cleanup - glFinish(); - glDeleteTextures(1, &mLeftTrail.name); - glDeleteTextures(1, &mRightTrail.name); - glDeleteTextures(1, &mBrightSpot.name); - return false; -} - -// --------------------------------------------------------------------------- - -} -; // namespace android diff --git a/libs/surfaceflinger/BootAnimation.h b/libs/surfaceflinger/BootAnimation.h deleted file mode 100644 index b20cea0..0000000 --- a/libs/surfaceflinger/BootAnimation.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_BOOTANIMATION_H -#define ANDROID_BOOTANIMATION_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/threads.h> -#include <utils/AssetManager.h> - -#include <ui/ISurfaceComposer.h> -#include <ui/SurfaceComposerClient.h> - -#include <EGL/egl.h> -#include <GLES/gl.h> - -#include "Barrier.h" - -class SkBitmap; - -namespace android { - -class AssetManager; -class EGLNativeWindowSurface; - -// --------------------------------------------------------------------------- - -class BootAnimation : public Thread -{ -public: - BootAnimation(const sp<ISurfaceComposer>& composer); - virtual ~BootAnimation(); - - const sp<SurfaceComposerClient>& session() const; - virtual void requestExit(); - -private: - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void onFirstRef(); - - struct Texture { - GLint w; - GLint h; - GLuint name; - }; - - status_t initTexture(Texture* texture, AssetManager& asset, const char* name); - bool android(); - bool cylon(); - - sp<SurfaceComposerClient> mSession; - AssetManager mAssets; - Texture mLeftTrail; - Texture mRightTrail; - Texture mBrightSpot; - Texture mAndroid[3]; - int mWidth; - int mHeight; - EGLDisplay mDisplay; - EGLDisplay mContext; - EGLDisplay mSurface; - sp<Surface> mFlingerSurface; - sp<EGLNativeWindowSurface> mNativeWindowSurface; - Barrier mBarrier; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_BOOTANIMATION_H diff --git a/libs/surfaceflinger/CPUGauge.cpp b/libs/surfaceflinger/CPUGauge.cpp deleted file mode 100644 index 74a9270..0000000 --- a/libs/surfaceflinger/CPUGauge.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "CPUGauge" - -#include <stdint.h> -#include <limits.h> -#include <sys/types.h> -#include <math.h> - -#include <utils/threads.h> -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <ui/PixelFormat.h> -#include <ui/Rect.h> -#include <ui/Region.h> -#include <ui/DisplayInfo.h> -#include <ui/ISurfaceComposer.h> -#include <ui/ISurfaceFlingerClient.h> - -#include <pixelflinger/pixelflinger.h> - -#include "CPUGauge.h" - -namespace android { - -CPUGauge::CPUGauge( const sp<ISurfaceComposer>& composer, - nsecs_t interval, - int clock, - int refclock) - : Thread(false), - mInterval(interval), mClock(clock), mRefClock(refclock), - mReferenceTime(0), - mReferenceWorkingTime(0), mCpuUsage(0), - mRefIdleTime(0), mIdleTime(0) -{ - mFd = fopen("/proc/stat", "r"); - setvbuf(mFd, NULL, _IONBF, 0); - - mSession = SurfaceComposerClient::clientForConnection( - composer->createConnection()->asBinder()); -} - -CPUGauge::~CPUGauge() -{ - fclose(mFd); -} - -const sp<SurfaceComposerClient>& CPUGauge::session() const -{ - return mSession; -} - -void CPUGauge::onFirstRef() -{ - run("CPU Gauge"); -} - -status_t CPUGauge::readyToRun() -{ - LOGI("Starting CPU gauge..."); - return NO_ERROR; -} - -bool CPUGauge::threadLoop() -{ - DisplayInfo dinfo; - session()->getDisplayInfo(0, &dinfo); - sp<Surface> s(session()->createSurface(getpid(), 0, dinfo.w, 4, PIXEL_FORMAT_OPAQUE)); - session()->openTransaction(); - s->setLayer(INT_MAX); - session()->closeTransaction(); - - static const GGLfixed colors[4][4] = { - { 0x00000, 0x10000, 0x00000, 0x10000 }, - { 0x10000, 0x10000, 0x00000, 0x10000 }, - { 0x10000, 0x00000, 0x00000, 0x10000 }, - { 0x00000, 0x00000, 0x00000, 0x10000 }, - }; - - GGLContext* gl; - gglInit(&gl); - gl->activeTexture(gl, 0); - gl->disable(gl, GGL_TEXTURE_2D); - gl->disable(gl, GGL_BLEND); - - const int w = dinfo.w; - - while(!exitPending()) - { - mLock.lock(); - const float cpuUsage = this->cpuUsage(); - const float totalCpuUsage = 1.0f - idle(); - mLock.unlock(); - - Surface::SurfaceInfo info; - s->lock(&info); - GGLSurface fb; - fb.version = sizeof(GGLSurface); - fb.width = info.w; - fb.height = info.h; - fb.stride = info.w; - fb.format = info.format; - fb.data = (GGLubyte*)info.bits; - - gl->colorBuffer(gl, &fb); - gl->color4xv(gl, colors[3]); - gl->recti(gl, 0, 0, w, 4); - gl->color4xv(gl, colors[2]); // red - gl->recti(gl, 0, 0, int(totalCpuUsage*w), 2); - gl->color4xv(gl, colors[0]); // green - gl->recti(gl, 0, 2, int(cpuUsage*w), 4); - - s->unlockAndPost(); - - usleep(ns2us(mInterval)); - } - - gglUninit(gl); - return false; -} - -void CPUGauge::sample() -{ - if (mLock.tryLock() == NO_ERROR) { - const nsecs_t now = systemTime(mRefClock); - const nsecs_t referenceTime = now-mReferenceTime; - if (referenceTime >= mInterval) { - const float reftime = 1.0f / referenceTime; - const nsecs_t nowWorkingTime = systemTime(mClock); - - char buf[256]; - fgets(buf, 256, mFd); - rewind(mFd); - char *str = buf+5; - char const * const usermode = strsep(&str, " "); (void)usermode; - char const * const usernice = strsep(&str, " "); (void)usernice; - char const * const systemmode = strsep(&str, " ");(void)systemmode; - char const * const idle = strsep(&str, " "); - const nsecs_t nowIdleTime = atoi(idle) * 10000000LL; - mIdleTime = float(nowIdleTime - mRefIdleTime) * reftime; - mRefIdleTime = nowIdleTime; - - const nsecs_t workingTime = nowWorkingTime - mReferenceWorkingTime; - const float newCpuUsage = float(workingTime) * reftime; - if (mCpuUsage != newCpuUsage) { - mCpuUsage = newCpuUsage; - mReferenceWorkingTime = nowWorkingTime; - mReferenceTime = now; - } - } - mLock.unlock(); - } -} - - -}; // namespace android diff --git a/libs/surfaceflinger/CPUGauge.h b/libs/surfaceflinger/CPUGauge.h deleted file mode 100644 index 5bb53c0..0000000 --- a/libs/surfaceflinger/CPUGauge.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_CPUGAUGE_H -#define ANDROID_CPUGAUGE_H - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Timers.h> - -#include <ui/SurfaceComposerClient.h> - -namespace android { - -class CPUGauge : public Thread -{ -public: - CPUGauge( const sp<ISurfaceComposer>& composer, - nsecs_t interval=s2ns(1), - int clock=SYSTEM_TIME_THREAD, - int refclock=SYSTEM_TIME_MONOTONIC); - - ~CPUGauge(); - - const sp<SurfaceComposerClient>& session() const; - - void sample(); - - inline float cpuUsage() const { return mCpuUsage; } - inline float idle() const { return mIdleTime; } - -private: - virtual void onFirstRef(); - virtual status_t readyToRun(); - virtual bool threadLoop(); - - Mutex mLock; - - sp<SurfaceComposerClient> mSession; - - const nsecs_t mInterval; - const int mClock; - const int mRefClock; - - nsecs_t mReferenceTime; - nsecs_t mReferenceWorkingTime; - float mCpuUsage; - nsecs_t mRefIdleTime; - float mIdleTime; - FILE* mFd; -}; - - -}; // namespace android - -#endif // ANDROID_CPUGAUGE_H diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp deleted file mode 100644 index f14d7e9..0000000 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <math.h> - -#include <cutils/properties.h> - -#include <utils/Log.h> - -#include <ui/EGLDisplaySurface.h> - -#include <GLES/gl.h> -#include <EGL/eglext.h> - - -#include "DisplayHardware/DisplayHardware.h" - -#include <hardware/copybit.h> -#include <hardware/overlay.h> - -using namespace android; - -static __attribute__((noinline)) -const char *egl_strerror(EGLint err) -{ - switch (err){ - case EGL_SUCCESS: return "EGL_SUCCESS"; - case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; - case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; - case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; - case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; - case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; - case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; - case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; - case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; - case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; - case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; - case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; - case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; - case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; - case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; - default: return "UNKNOWN"; - } -} - -static __attribute__((noinline)) -void checkGLErrors() -{ - GLenum error = glGetError(); - if (error != GL_NO_ERROR) - LOGE("GL error 0x%04x", int(error)); -} - -static __attribute__((noinline)) -void checkEGLErrors(const char* token) -{ - EGLint error = eglGetError(); - // GLESonGL seems to be returning 0 when there is no errors? - if (error && error != EGL_SUCCESS) - LOGE("%s error 0x%04x (%s)", - token, int(error), egl_strerror(error)); -} - - -/* - * Initialize the display to the specified values. - * - */ - -DisplayHardware::DisplayHardware( - const sp<SurfaceFlinger>& flinger, - uint32_t dpy) - : DisplayHardwareBase(flinger, dpy) -{ - init(dpy); -} - -DisplayHardware::~DisplayHardware() -{ - fini(); -} - -float DisplayHardware::getDpiX() const { return mDpiX; } -float DisplayHardware::getDpiY() const { return mDpiY; } -float DisplayHardware::getDensity() const { return mDensity; } -float DisplayHardware::getRefreshRate() const { return mRefreshRate; } -int DisplayHardware::getWidth() const { return mWidth; } -int DisplayHardware::getHeight() const { return mHeight; } -PixelFormat DisplayHardware::getFormat() const { return mFormat; } - -void DisplayHardware::init(uint32_t dpy) -{ - // initialize EGL - const EGLint attribs[] = { - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, - EGL_DEPTH_SIZE, 0, - EGL_NONE - }; - EGLint w, h, dummy; - EGLint numConfigs, n; - EGLConfig config; - EGLSurface surface; - EGLContext context; - mFlags = 0; - - // TODO: all the extensions below should be queried through - // eglGetProcAddress(). - - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(display, NULL, NULL); - eglGetConfigs(display, NULL, 0, &numConfigs); - eglChooseConfig(display, attribs, &config, 1, &n); - - /* - * Gather EGL extensions - */ - - const char* const egl_extensions = eglQueryString( - display, EGL_EXTENSIONS); - - LOGI("EGL informations:"); - LOGI("# of configs : %d", numConfigs); - LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); - LOGI("version : %s", eglQueryString(display, EGL_VERSION)); - LOGI("extensions: %s", egl_extensions); - LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); - - // TODO: get this from the devfb driver (probably should be HAL module) - mFlags |= SWAP_RECTANGLE_EXTENSION; - - // TODO: get the real "update_on_demand" behavior (probably should be HAL module) - mFlags |= UPDATE_ON_DEMAND; - - if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { - if (dummy == EGL_SLOW_CONFIG) - mFlags |= SLOW_CONFIG; - } - - /* - * Create our main surface - */ - - mDisplaySurface = new EGLDisplaySurface(); - - surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL); - //checkEGLErrors("eglCreateDisplaySurfaceANDROID"); - - if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { - if (dummy == EGL_BUFFER_PRESERVED) { - mFlags |= BUFFER_PRESERVED; - } - } - - GLint value = EGL_UNKNOWN; - eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value); - if (value == EGL_UNKNOWN) { - mDpiX = 160.0f; - } else { - mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING; - } - value = EGL_UNKNOWN; - eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value); - if (value == EGL_UNKNOWN) { - mDpiY = 160.0f; - } else { - mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING; - } - mRefreshRate = 60.f; // TODO: get the real refresh rate - - - char property[PROPERTY_VALUE_MAX]; - if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { - LOGW("ro.sf.lcd_density not defined, using 160 dpi by default."); - strcpy(property, "160"); - } - mDensity = atoi(property) * (1.0f/160.0f); - - - /* - * Create our OpenGL ES context - */ - - context = eglCreateContext(display, config, NULL, NULL); - //checkEGLErrors("eglCreateContext"); - - eglQuerySurface(display, surface, EGL_WIDTH, &mWidth); - eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight); - - - /* - * Gather OpenGL ES extensions - */ - - eglMakeCurrent(display, surface, surface, context); - const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS); - LOGI("OpenGL informations:"); - LOGI("vendor : %s", glGetString(GL_VENDOR)); - LOGI("renderer : %s", glGetString(GL_RENDERER)); - LOGI("version : %s", glGetString(GL_VERSION)); - LOGI("extensions: %s", gl_extensions); - - if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) { - mFlags |= NPOT_EXTENSION; - } - if (strstr(gl_extensions, "GL_OES_draw_texture")) { - mFlags |= DRAW_TEXTURE_EXTENSION; - } - if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) { - mFlags |= DIRECT_TEXTURE; - } - - // Unbind the context from this thread - eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - mDisplay = display; - mConfig = config; - mSurface = surface; - mContext = context; - mFormat = GGL_PIXEL_FORMAT_RGB_565; - - hw_module_t const* module; - - mBlitEngine = NULL; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } - - mOverlayEngine = NULL; - if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { - overlay_control_open(module, &mOverlayEngine); - } -} - -/* - * Clean up. Throw out our local state. - * - * (It's entirely possible we'll never get here, since this is meant - * for real hardware, which doesn't restart.) - */ - -void DisplayHardware::fini() -{ - eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglTerminate(mDisplay); - copybit_close(mBlitEngine); - overlay_control_close(mOverlayEngine); -} - -void DisplayHardware::releaseScreen() const -{ - DisplayHardwareBase::releaseScreen(); -} - -void DisplayHardware::acquireScreen() const -{ - DisplayHardwareBase::acquireScreen(); -} - -void DisplayHardware::getDisplaySurface(copybit_image_t* img) const -{ - img->w = mDisplaySurface->stride; - img->h = mDisplaySurface->height; - img->format = mDisplaySurface->format; - img->offset = mDisplaySurface->offset; - img->base = (void*)mDisplaySurface->base; - img->fd = mDisplaySurface->fd; -} - -void DisplayHardware::getDisplaySurface(GGLSurface* fb) const -{ - fb->version= sizeof(GGLSurface); - fb->width = mDisplaySurface->width; - fb->height = mDisplaySurface->height; - fb->stride = mDisplaySurface->stride; - fb->format = mDisplaySurface->format; - fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset; -} - -uint32_t DisplayHardware::getPageFlipCount() const { - return mDisplaySurface->getPageFlipCount(); -} - -/* - * "Flip" the front and back buffers. - */ - -void DisplayHardware::flip(const Region& dirty) const -{ - checkGLErrors(); - - EGLDisplay dpy = mDisplay; - EGLSurface surface = mSurface; - - Region newDirty(dirty); - newDirty.andSelf(Rect(mWidth, mHeight)); - - if (mFlags & BUFFER_PRESERVED) { - const Region copyback(mDirty.subtract(newDirty)); - mDirty = newDirty; - mDisplaySurface->copyFrontToBack(copyback); - } - - if (mFlags & SWAP_RECTANGLE_EXTENSION) { - const Rect& b(newDirty.bounds()); - mDisplaySurface->setSwapRectangle( - b.left, b.top, b.width(), b.height()); - } - - eglSwapBuffers(dpy, surface); - checkEGLErrors("eglSwapBuffers"); - - // for debugging - //glClearColor(1,0,0,0); - //glClear(GL_COLOR_BUFFER_BIT); -} - -uint32_t DisplayHardware::getFlags() const -{ - return mFlags; -} - -void DisplayHardware::makeCurrent() const -{ - eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); -} - -void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { - mDisplaySurface->copyFrontToImage(front); -} - -void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { - mDisplaySurface->copyBackToImage(front); -} diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h deleted file mode 100644 index 550a4d1..0000000 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_DISPLAY_HARDWARE_H -#define ANDROID_DISPLAY_HARDWARE_H - -#include <stdlib.h> - -#include <ui/PixelFormat.h> -#include <ui/Region.h> - -#include <EGL/egl.h> - -#include "DisplayHardware/DisplayHardwareBase.h" - -struct overlay_control_device_t; -struct copybit_device_t; -struct copybit_image_t; -struct copybit_t; - -namespace android { - -class EGLDisplaySurface; - -class DisplayHardware : public DisplayHardwareBase -{ -public: - enum { - DIRECT_TEXTURE = 0x00000002, - SWAP_RECTANGLE_EXTENSION= 0x00000004, - COPY_BITS_EXTENSION = 0x00000008, - NPOT_EXTENSION = 0x00000100, - DRAW_TEXTURE_EXTENSION = 0x00000200, - BUFFER_PRESERVED = 0x00010000, - UPDATE_ON_DEMAND = 0x00020000, // video driver feature - SLOW_CONFIG = 0x00040000, // software - }; - - DisplayHardware( - const sp<SurfaceFlinger>& flinger, - uint32_t displayIndex); - - ~DisplayHardware(); - - void releaseScreen() const; - void acquireScreen() const; - - // Flip the front and back buffers if the back buffer is "dirty". Might - // be instantaneous, might involve copying the frame buffer around. - void flip(const Region& dirty) const; - - float getDpiX() const; - float getDpiY() const; - float getRefreshRate() const; - float getDensity() const; - int getWidth() const; - int getHeight() const; - PixelFormat getFormat() const; - uint32_t getFlags() const; - void makeCurrent() const; - - uint32_t getPageFlipCount() const; - void getDisplaySurface(copybit_image_t* img) const; - void getDisplaySurface(GGLSurface* fb) const; - EGLDisplay getEGLDisplay() const { return mDisplay; } - copybit_device_t* getBlitEngine() const { return mBlitEngine; } - overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } - - void copyFrontToImage(const copybit_image_t& front) const; - void copyBackToImage(const copybit_image_t& front) const; - - Rect bounds() const { - return Rect(mWidth, mHeight); - } - -private: - void init(uint32_t displayIndex) __attribute__((noinline)); - void fini() __attribute__((noinline)); - - EGLDisplay mDisplay; - EGLSurface mSurface; - EGLContext mContext; - EGLConfig mConfig; - float mDpiX; - float mDpiY; - float mRefreshRate; - float mDensity; - int mWidth; - int mHeight; - PixelFormat mFormat; - uint32_t mFlags; - mutable Region mDirty; - sp<EGLDisplaySurface> mDisplaySurface; - copybit_device_t* mBlitEngine; - overlay_control_device_t* mOverlayEngine; -}; - -}; // namespace android - -#endif // ANDROID_DISPLAY_HARDWARE_H diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp deleted file mode 100644 index f75e5c2..0000000 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <assert.h> -#include <errno.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> -#include <termios.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/resource.h> - -#include <linux/unistd.h> - -#include <utils/Log.h> - -#include "DisplayHardware/DisplayHardwareBase.h" -#include "SurfaceFlinger.h" - -// ---------------------------------------------------------------------------- -// the sim build doesn't have gettid - -#ifndef HAVE_GETTID -# define gettid getpid -#endif - -// ---------------------------------------------------------------------------- -namespace android { - -static char const * kSleepFileName = "/sys/power/wait_for_fb_sleep"; -static char const * kWakeFileName = "/sys/power/wait_for_fb_wake"; -static char const * const kOldSleepFileName = "/sys/android_power/wait_for_fb_sleep"; -static char const * const kOldWakeFileName = "/sys/android_power/wait_for_fb_wake"; - -// This dir exists if the framebuffer console is present, either built into -// the kernel or loaded as a module. -static char const * const kFbconSysDir = "/sys/class/graphics/fbcon"; - -// ---------------------------------------------------------------------------- - -DisplayHardwareBase::DisplayEventThreadBase::DisplayEventThreadBase( - const sp<SurfaceFlinger>& flinger) - : Thread(false), mFlinger(flinger) { -} - -DisplayHardwareBase::DisplayEventThreadBase::~DisplayEventThreadBase() { -} - -// ---------------------------------------------------------------------------- - -DisplayHardwareBase::DisplayEventThread::DisplayEventThread( - const sp<SurfaceFlinger>& flinger) - : DisplayEventThreadBase(flinger) -{ -} - -DisplayHardwareBase::DisplayEventThread::~DisplayEventThread() -{ -} - -bool DisplayHardwareBase::DisplayEventThread::threadLoop() -{ - int err = 0; - char buf; - int fd; - - fd = open(kSleepFileName, O_RDONLY, 0); - do { - err = read(fd, &buf, 1); - } while (err < 0 && errno == EINTR); - close(fd); - LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno)); - if (err >= 0) { - sp<SurfaceFlinger> flinger = mFlinger.promote(); - LOGD("About to give-up screen, flinger = %p", flinger.get()); - if (flinger != 0) { - mBarrier.close(); - flinger->screenReleased(0); - mBarrier.wait(); - } - } - fd = open(kWakeFileName, O_RDONLY, 0); - do { - err = read(fd, &buf, 1); - } while (err < 0 && errno == EINTR); - close(fd); - LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno)); - if (err >= 0) { - sp<SurfaceFlinger> flinger = mFlinger.promote(); - LOGD("Screen about to return, flinger = %p", flinger.get()); - if (flinger != 0) - flinger->screenAcquired(0); - } - return true; -} - -status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const -{ - mBarrier.open(); - return NO_ERROR; -} - -status_t DisplayHardwareBase::DisplayEventThread::readyToRun() -{ - if (access(kSleepFileName, R_OK) || access(kWakeFileName, R_OK)) { - if (access(kOldSleepFileName, R_OK) || access(kOldWakeFileName, R_OK)) { - LOGE("Couldn't open %s or %s", kSleepFileName, kWakeFileName); - return NO_INIT; - } - kSleepFileName = kOldSleepFileName; - kWakeFileName = kOldWakeFileName; - } - return NO_ERROR; -} - -status_t DisplayHardwareBase::DisplayEventThread::initCheck() const -{ - return (((access(kSleepFileName, R_OK) == 0 && - access(kWakeFileName, R_OK) == 0) || - (access(kOldSleepFileName, R_OK) == 0 && - access(kOldWakeFileName, R_OK) == 0)) && - access(kFbconSysDir, F_OK) != 0) ? NO_ERROR : NO_INIT; -} - -// ---------------------------------------------------------------------------- - -pid_t DisplayHardwareBase::ConsoleManagerThread::sSignalCatcherPid = 0; - -DisplayHardwareBase::ConsoleManagerThread::ConsoleManagerThread( - const sp<SurfaceFlinger>& flinger) - : DisplayEventThreadBase(flinger), consoleFd(-1) -{ - sSignalCatcherPid = 0; - - // create a new console - char const * const ttydev = "/dev/tty0"; - int fd = open(ttydev, O_RDWR | O_SYNC); - if (fd<0) { - LOGE("Can't open %s", ttydev); - this->consoleFd = -errno; - return; - } - - // to make sure that we are in text mode - int res = ioctl(fd, KDSETMODE, (void*) KD_TEXT); - if (res<0) { - LOGE("ioctl(%d, KDSETMODE, ...) failed, res %d (%s)", - fd, res, strerror(errno)); - } - - // get the current console - struct vt_stat vs; - res = ioctl(fd, VT_GETSTATE, &vs); - if (res<0) { - LOGE("ioctl(%d, VT_GETSTATE, ...) failed, res %d (%s)", - fd, res, strerror(errno)); - this->consoleFd = -errno; - return; - } - - // switch to console 7 (which is what X normaly uses) - int vtnum = 7; - do { - res = ioctl(fd, VT_ACTIVATE, (void*)vtnum); - } while(res < 0 && errno == EINTR); - if (res<0) { - LOGE("ioctl(%d, VT_ACTIVATE, ...) failed, %d (%s) for %d", - fd, errno, strerror(errno), vtnum); - this->consoleFd = -errno; - return; - } - - do { - res = ioctl(fd, VT_WAITACTIVE, (void*)vtnum); - } while(res < 0 && errno == EINTR); - if (res<0) { - LOGE("ioctl(%d, VT_WAITACTIVE, ...) failed, %d %d %s for %d", - fd, res, errno, strerror(errno), vtnum); - this->consoleFd = -errno; - return; - } - - // open the new console - close(fd); - fd = open(ttydev, O_RDWR | O_SYNC); - if (fd<0) { - LOGE("Can't open new console %s", ttydev); - this->consoleFd = -errno; - return; - } - - /* disable console line buffer, echo, ... */ - struct termios ttyarg; - ioctl(fd, TCGETS , &ttyarg); - ttyarg.c_iflag = 0; - ttyarg.c_lflag = 0; - ioctl(fd, TCSETS , &ttyarg); - - // set up signals so we're notified when the console changes - // we can't use SIGUSR1 because it's used by the java-vm - vm.mode = VT_PROCESS; - vm.waitv = 0; - vm.relsig = SIGUSR2; - vm.acqsig = SIGUNUSED; - vm.frsig = 0; - - struct sigaction act; - sigemptyset(&act.sa_mask); - act.sa_handler = sigHandler; - act.sa_flags = 0; - sigaction(vm.relsig, &act, NULL); - - sigemptyset(&act.sa_mask); - act.sa_handler = sigHandler; - act.sa_flags = 0; - sigaction(vm.acqsig, &act, NULL); - - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, vm.relsig); - sigaddset(&mask, vm.acqsig); - sigprocmask(SIG_BLOCK, &mask, NULL); - - // switch to graphic mode - res = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS); - LOGW_IF(res<0, - "ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, res %d", fd, res); - - this->prev_vt_num = vs.v_active; - this->vt_num = vtnum; - this->consoleFd = fd; -} - -DisplayHardwareBase::ConsoleManagerThread::~ConsoleManagerThread() -{ - if (this->consoleFd >= 0) { - int fd = this->consoleFd; - int prev_vt_num = this->prev_vt_num; - int res; - ioctl(fd, KDSETMODE, (void*)KD_TEXT); - do { - res = ioctl(fd, VT_ACTIVATE, (void*)prev_vt_num); - } while(res < 0 && errno == EINTR); - do { - res = ioctl(fd, VT_WAITACTIVE, (void*)prev_vt_num); - } while(res < 0 && errno == EINTR); - close(fd); - char const * const ttydev = "/dev/tty0"; - fd = open(ttydev, O_RDWR | O_SYNC); - ioctl(fd, VT_DISALLOCATE, 0); - close(fd); - } -} - -status_t DisplayHardwareBase::ConsoleManagerThread::readyToRun() -{ - if (this->consoleFd >= 0) { - sSignalCatcherPid = gettid(); - - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, vm.relsig); - sigaddset(&mask, vm.acqsig); - sigprocmask(SIG_BLOCK, &mask, NULL); - - int res = ioctl(this->consoleFd, VT_SETMODE, &vm); - if (res<0) { - LOGE("ioctl(%d, VT_SETMODE, ...) failed, %d (%s)", - this->consoleFd, errno, strerror(errno)); - } - return NO_ERROR; - } - return this->consoleFd; -} - -void DisplayHardwareBase::ConsoleManagerThread::requestExit() -{ - Thread::requestExit(); - if (sSignalCatcherPid != 0) { - // wake the thread up - kill(sSignalCatcherPid, SIGINT); - // wait for it... - } -} - -void DisplayHardwareBase::ConsoleManagerThread::sigHandler(int sig) -{ - // resend the signal to our signal catcher thread - LOGW("received signal %d in thread %d, resending to %d", - sig, gettid(), sSignalCatcherPid); - - // we absolutely need the delays below because without them - // our main thread never gets a chance to handle the signal. - usleep(10000); - kill(sSignalCatcherPid, sig); - usleep(10000); -} - -status_t DisplayHardwareBase::ConsoleManagerThread::releaseScreen() const -{ - int fd = this->consoleFd; - int err = ioctl(fd, VT_RELDISP, (void*)1); - LOGE_IF(err<0, "ioctl(%d, VT_RELDISP, 1) failed %d (%s)", - fd, errno, strerror(errno)); - return (err<0) ? (-errno) : status_t(NO_ERROR); -} - -bool DisplayHardwareBase::ConsoleManagerThread::threadLoop() -{ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, vm.relsig); - sigaddset(&mask, vm.acqsig); - - int sig = 0; - sigwait(&mask, &sig); - - if (sig == vm.relsig) { - sp<SurfaceFlinger> flinger = mFlinger.promote(); - //LOGD("About to give-up screen, flinger = %p", flinger.get()); - if (flinger != 0) - flinger->screenReleased(0); - } else if (sig == vm.acqsig) { - sp<SurfaceFlinger> flinger = mFlinger.promote(); - //LOGD("Screen about to return, flinger = %p", flinger.get()); - if (flinger != 0) - flinger->screenAcquired(0); - } - - return true; -} - -status_t DisplayHardwareBase::ConsoleManagerThread::initCheck() const -{ - return consoleFd >= 0 ? NO_ERROR : NO_INIT; -} - -// ---------------------------------------------------------------------------- - -DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger, - uint32_t displayIndex) - : mCanDraw(true) -{ - mDisplayEventThread = new DisplayEventThread(flinger); - if (mDisplayEventThread->initCheck() != NO_ERROR) { - // fall-back on the console - mDisplayEventThread = new ConsoleManagerThread(flinger); - } -} - -DisplayHardwareBase::~DisplayHardwareBase() -{ - // request exit - mDisplayEventThread->requestExitAndWait(); -} - - -bool DisplayHardwareBase::canDraw() const -{ - return mCanDraw; -} - -void DisplayHardwareBase::releaseScreen() const -{ - status_t err = mDisplayEventThread->releaseScreen(); - if (err >= 0) { - //LOGD("screen given-up"); - mCanDraw = false; - } -} - -void DisplayHardwareBase::acquireScreen() const -{ - status_t err = mDisplayEventThread->acquireScreen(); - if (err >= 0) { - //LOGD("screen returned"); - mCanDraw = true; - } -} - -}; // namespace android diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h deleted file mode 100644 index 8369bb8..0000000 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_DISPLAY_HARDWARE_BASE_H -#define ANDROID_DISPLAY_HARDWARE_BASE_H - -#include <stdint.h> -#include <utils/RefBase.h> -#include <utils/threads.h> -#include <linux/kd.h> -#include <linux/vt.h> -#include "Barrier.h" - -namespace android { - -class SurfaceFlinger; - -class DisplayHardwareBase -{ -public: - DisplayHardwareBase( - const sp<SurfaceFlinger>& flinger, - uint32_t displayIndex); - - ~DisplayHardwareBase(); - - // console managment - void releaseScreen() const; - void acquireScreen() const; - bool canDraw() const; - -private: - class DisplayEventThreadBase : public Thread { - protected: - wp<SurfaceFlinger> mFlinger; - public: - DisplayEventThreadBase(const sp<SurfaceFlinger>& flinger); - virtual ~DisplayEventThreadBase(); - virtual void onFirstRef() { - run("DisplayEventThread", PRIORITY_URGENT_DISPLAY); - } - virtual status_t acquireScreen() const { return NO_ERROR; }; - virtual status_t releaseScreen() const { return NO_ERROR; }; - virtual status_t initCheck() const = 0; - }; - - class DisplayEventThread : public DisplayEventThreadBase - { - mutable Barrier mBarrier; - public: - DisplayEventThread(const sp<SurfaceFlinger>& flinger); - virtual ~DisplayEventThread(); - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual status_t releaseScreen() const; - virtual status_t initCheck() const; - }; - - class ConsoleManagerThread : public DisplayEventThreadBase - { - int consoleFd; - int vt_num; - int prev_vt_num; - vt_mode vm; - static void sigHandler(int sig); - static pid_t sSignalCatcherPid; - public: - ConsoleManagerThread(const sp<SurfaceFlinger>& flinger); - virtual ~ConsoleManagerThread(); - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void requestExit(); - virtual status_t releaseScreen() const; - virtual status_t initCheck() const; - }; - - sp<DisplayEventThreadBase> mDisplayEventThread; - mutable int mCanDraw; -}; - -}; // namespace android - -#endif // ANDROID_DISPLAY_HARDWARE_BASE_H diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp deleted file mode 100644 index eb75f99..0000000 --- a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <math.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <cutils/log.h> -#include <cutils/properties.h> - -#include <utils/IBinder.h> -#include <utils/MemoryDealer.h> -#include <utils/MemoryBase.h> -#include <utils/MemoryHeapPmem.h> -#include <utils/MemoryHeapBase.h> -#include <utils/IPCThreadState.h> -#include <utils/StopWatch.h> - -#include <ui/ISurfaceComposer.h> - -#include "VRamHeap.h" -#include "GPUHardware.h" - -#if HAVE_ANDROID_OS -#include <linux/android_pmem.h> -#endif - -#include "GPUHardware/GPUHardware.h" - - -/* - * Manage the GPU. This implementation is very specific to the G1. - * There are no abstraction here. - * - * All this code will soon go-away and be replaced by a new architecture - * for managing graphics accelerators. - * - * In the meantime, it is conceptually possible to instantiate a - * GPUHardwareInterface for another GPU (see GPUFactory at the bottom - * of this file); practically... doubtful. - * - */ - -namespace android { - -// --------------------------------------------------------------------------- - -class GPUClientHeap; -class GPUAreaHeap; - -class GPUHardware : public GPUHardwareInterface, public IBinder::DeathRecipient -{ -public: - static const int GPU_RESERVED_SIZE; - static const int GPUR_SIZE; - - GPUHardware(); - virtual ~GPUHardware(); - - virtual void revoke(int pid); - virtual sp<MemoryDealer> request(int pid); - virtual status_t request(int pid, - const sp<IGPUCallback>& callback, - ISurfaceComposer::gpu_info_t* gpu); - - virtual status_t friendlyRevoke(); - virtual void unconditionalRevoke(); - - virtual pid_t getOwner() const { return mOwner; } - - // used for debugging only... - virtual sp<SimpleBestFitAllocator> getAllocator() const; - -private: - - - enum { - NO_OWNER = -1, - }; - - struct GPUArea { - sp<GPUAreaHeap> heap; - sp<MemoryHeapPmem> clientHeap; - sp<IMemory> map(); - }; - - struct Client { - pid_t pid; - GPUArea smi; - GPUArea ebi; - GPUArea reg; - void createClientHeaps(); - void revokeAllHeaps(); - }; - - Client& getClientLocked(pid_t pid); - status_t requestLocked(int pid); - void releaseLocked(); - void takeBackGPULocked(); - void registerCallbackLocked(const sp<IGPUCallback>& callback, - Client& client); - - virtual void binderDied(const wp<IBinder>& who); - - mutable Mutex mLock; - sp<GPUAreaHeap> mSMIHeap; - sp<GPUAreaHeap> mEBIHeap; - sp<GPUAreaHeap> mREGHeap; - - KeyedVector<pid_t, Client> mClients; - DefaultKeyedVector< wp<IBinder>, pid_t > mRegisteredClients; - - pid_t mOwner; - - sp<MemoryDealer> mCurrentAllocator; - sp<IGPUCallback> mCallback; - - sp<SimpleBestFitAllocator> mAllocator; - - Condition mCondition; -}; - -// size reserved for GPU surfaces -// 1200 KB fits exactly: -// - two 320*480 16-bits double-buffered surfaces -// - one 320*480 32-bits double-buffered surface -// - one 320*240 16-bits double-buffered, 4x anti-aliased surface -const int GPUHardware::GPU_RESERVED_SIZE = 1200 * 1024; -const int GPUHardware::GPUR_SIZE = 1 * 1024 * 1024; - -// --------------------------------------------------------------------------- - -/* - * GPUHandle is a special IMemory given to the client. It represents their - * handle to the GPU. Once they give it up, they loose GPU access, or if - * they explicitly revoke their access through the binder code 1000. - * In both cases, this triggers a callback to revoke() - * first, and then actually powers down the chip. - * - * In the case of a misbehaving app, GPUHardware can ask for an immediate - * release of the GPU to the target process which should answer by calling - * code 1000 on GPUHandle. If it doesn't in a timely manner, the GPU will - * be revoked from under their feet. - * - * We should never hold a strong reference on GPUHandle. In practice this - * shouldn't be a big issue though because clients should use code 1000 and - * not rely on the dtor being called. - * - */ - -class GPUClientHeap : public MemoryHeapPmem -{ -public: - GPUClientHeap(const wp<GPUHardware>& gpu, - const sp<MemoryHeapBase>& heap) - : MemoryHeapPmem(heap), mGPU(gpu) { } -protected: - wp<GPUHardware> mGPU; -}; - -class GPUAreaHeap : public MemoryHeapBase -{ -public: - GPUAreaHeap(const wp<GPUHardware>& gpu, - const char* const vram, size_t size=0, size_t reserved=0) - : MemoryHeapBase(vram, size), mGPU(gpu) { - if (base() != MAP_FAILED) { - if (reserved == 0) - reserved = virtualSize(); - mAllocator = new SimpleBestFitAllocator(reserved); - } - } - virtual sp<MemoryHeapPmem> createClientHeap() { - sp<MemoryHeapBase> parentHeap(this); - return new GPUClientHeap(mGPU, parentHeap); - } - virtual const sp<SimpleBestFitAllocator>& getAllocator() const { - return mAllocator; - } -private: - sp<SimpleBestFitAllocator> mAllocator; -protected: - wp<GPUHardware> mGPU; -}; - -class GPURegisterHeap : public GPUAreaHeap -{ -public: - GPURegisterHeap(const sp<GPUHardware>& gpu) - : GPUAreaHeap(gpu, "/dev/hw3d", GPUHardware::GPUR_SIZE) { } - virtual sp<MemoryHeapPmem> createClientHeap() { - sp<MemoryHeapBase> parentHeap(this); - return new MemoryHeapRegs(mGPU, parentHeap); - } -private: - class MemoryHeapRegs : public GPUClientHeap { - public: - MemoryHeapRegs(const wp<GPUHardware>& gpu, - const sp<MemoryHeapBase>& heap) - : GPUClientHeap(gpu, heap) { } - sp<MemoryHeapPmem::MemoryPmem> createMemory(size_t offset, size_t size); - virtual void revoke(); - private: - class GPUHandle : public MemoryHeapPmem::MemoryPmem { - public: - GPUHandle(const sp<GPUHardware>& gpu, - const sp<MemoryHeapPmem>& heap) - : MemoryHeapPmem::MemoryPmem(heap), - mGPU(gpu), mOwner(gpu->getOwner()) { } - virtual ~GPUHandle(); - virtual sp<IMemoryHeap> getMemory( - ssize_t* offset, size_t* size) const; - virtual void revoke() { }; - virtual status_t onTransact( - uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags); - private: - void revokeNotification(); - wp<GPUHardware> mGPU; - pid_t mOwner; - }; - }; -}; - -GPURegisterHeap::MemoryHeapRegs::GPUHandle::~GPUHandle() { - //LOGD("GPUHandle %p released, revoking GPU", this); - revokeNotification(); -} -void GPURegisterHeap::MemoryHeapRegs::GPUHandle::revokeNotification() { - sp<GPUHardware> hw(mGPU.promote()); - if (hw != 0) { - hw->revoke(mOwner); - } -} -sp<IMemoryHeap> GPURegisterHeap::MemoryHeapRegs::GPUHandle::getMemory( - ssize_t* offset, size_t* size) const -{ - sp<MemoryHeapPmem> heap = getHeap(); - if (offset) *offset = 0; - if (size) *size = heap !=0 ? heap->virtualSize() : 0; - return heap; -} -status_t GPURegisterHeap::MemoryHeapRegs::GPUHandle::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - status_t err = BnMemory::onTransact(code, data, reply, flags); - if (err == UNKNOWN_TRANSACTION && code == 1000) { - int callingPid = IPCThreadState::self()->getCallingPid(); - //LOGD("pid %d voluntarily revoking gpu", callingPid); - if (callingPid == mOwner) { - revokeNotification(); - // we've revoked the GPU, don't do it again later when we - // are destroyed. - mGPU.clear(); - } else { - LOGW("%d revoking someone else's gpu? (owner=%d)", - callingPid, mOwner); - } - err = NO_ERROR; - } - return err; -} - -// --------------------------------------------------------------------------- - - -sp<MemoryHeapPmem::MemoryPmem> GPURegisterHeap::MemoryHeapRegs::createMemory( - size_t offset, size_t size) -{ - sp<GPUHandle> memory; - sp<GPUHardware> gpu = mGPU.promote(); - if (heapID()>0 && gpu!=0) { -#if HAVE_ANDROID_OS - /* this is where the GPU is powered on and the registers are mapped - * in the client */ - //LOGD("ioctl(HW3D_GRANT_GPU)"); - int err = ioctl(heapID(), HW3D_GRANT_GPU, base()); - if (err) { - // it can happen if the master heap has been closed already - // in which case the GPU already is revoked (app crash for - // instance). - LOGW("HW3D_GRANT_GPU failed (%s), mFD=%d, base=%p", - strerror(errno), heapID(), base()); - } - memory = new GPUHandle(gpu, this); -#endif - } - return memory; -} - -void GPURegisterHeap::MemoryHeapRegs::revoke() -{ - MemoryHeapPmem::revoke(); -#if HAVE_ANDROID_OS - if (heapID() > 0) { - //LOGD("ioctl(HW3D_REVOKE_GPU)"); - int err = ioctl(heapID(), HW3D_REVOKE_GPU, base()); - LOGE_IF(err, "HW3D_REVOKE_GPU failed (%s), mFD=%d, base=%p", - strerror(errno), heapID(), base()); - } -#endif -} - -/*****************************************************************************/ - -GPUHardware::GPUHardware() - : mOwner(NO_OWNER) -{ -} - -GPUHardware::~GPUHardware() -{ -} - -status_t GPUHardware::requestLocked(int pid) -{ - const int self_pid = getpid(); - if (pid == self_pid) { - // can't use GPU from surfaceflinger's process - return PERMISSION_DENIED; - } - - if (mOwner != pid) { - if (mREGHeap != 0) { - if (mOwner != NO_OWNER) { - // someone already has the gpu. - takeBackGPULocked(); - releaseLocked(); - } - } else { - // first time, initialize the stuff. - if (mSMIHeap == 0) - mSMIHeap = new GPUAreaHeap(this, "/dev/pmem_gpu0"); - if (mEBIHeap == 0) - mEBIHeap = new GPUAreaHeap(this, - "/dev/pmem_gpu1", 0, GPU_RESERVED_SIZE); - mREGHeap = new GPURegisterHeap(this); - mAllocator = mEBIHeap->getAllocator(); - if (mAllocator == NULL) { - // something went terribly wrong. - mSMIHeap.clear(); - mEBIHeap.clear(); - mREGHeap.clear(); - return INVALID_OPERATION; - } - } - Client& client = getClientLocked(pid); - mCurrentAllocator = new MemoryDealer(client.ebi.clientHeap, mAllocator); - mOwner = pid; - } - return NO_ERROR; -} - -sp<MemoryDealer> GPUHardware::request(int pid) -{ - sp<MemoryDealer> dealer; - Mutex::Autolock _l(mLock); - Client* client; - LOGD("pid %d requesting gpu surface (current owner = %d)", pid, mOwner); - if (requestLocked(pid) == NO_ERROR) { - dealer = mCurrentAllocator; - LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner); - } - return dealer; -} - -status_t GPUHardware::request(int pid, const sp<IGPUCallback>& callback, - ISurfaceComposer::gpu_info_t* gpu) -{ - if (callback == 0) - return BAD_VALUE; - - sp<IMemory> gpuHandle; - LOGD("pid %d requesting gpu core (owner = %d)", pid, mOwner); - Mutex::Autolock _l(mLock); - status_t err = requestLocked(pid); - if (err == NO_ERROR) { - // it's guaranteed to be there, be construction - Client& client = mClients.editValueFor(pid); - registerCallbackLocked(callback, client); - gpu->count = 2; - gpu->regions[0].region = client.smi.map(); - gpu->regions[1].region = client.ebi.map(); - gpu->regs = client.reg.map(); - gpu->regions[0].reserved = 0; - gpu->regions[1].reserved = GPU_RESERVED_SIZE; - if (gpu->regs != 0) { - //LOGD("gpu core granted to pid %d, handle base=%p", - // mOwner, gpu->regs->pointer()); - } - mCallback = callback; - } else { - LOGW("couldn't grant gpu core to pid %d", pid); - } - return err; -} - -void GPUHardware::revoke(int pid) -{ - Mutex::Autolock _l(mLock); - if (mOwner > 0) { - if (pid != mOwner) { - LOGW("GPU owned by %d, revoke from %d", mOwner, pid); - return; - } - //LOGD("revoke pid=%d, owner=%d", pid, mOwner); - // mOwner could be <0 if the same process acquired the GPU - // several times without releasing it first. - mCondition.signal(); - releaseLocked(); - } -} - -status_t GPUHardware::friendlyRevoke() -{ - Mutex::Autolock _l(mLock); - //LOGD("friendlyRevoke owner=%d", mOwner); - takeBackGPULocked(); - releaseLocked(); - return NO_ERROR; -} - -void GPUHardware::takeBackGPULocked() -{ - sp<IGPUCallback> callback = mCallback; - mCallback.clear(); - if (callback != 0) { - callback->gpuLost(); // one-way - mCondition.waitRelative(mLock, ms2ns(250)); - } -} - -void GPUHardware::releaseLocked() -{ - //LOGD("revoking gpu from pid %d", mOwner); - if (mOwner != NO_OWNER) { - // this may fail because the client might have died, and have - // been removed from the list. - ssize_t index = mClients.indexOfKey(mOwner); - if (index >= 0) { - Client& client(mClients.editValueAt(index)); - client.revokeAllHeaps(); - } - mOwner = NO_OWNER; - mCurrentAllocator.clear(); - mCallback.clear(); - } -} - -GPUHardware::Client& GPUHardware::getClientLocked(pid_t pid) -{ - ssize_t index = mClients.indexOfKey(pid); - if (index < 0) { - Client client; - client.pid = pid; - client.smi.heap = mSMIHeap; - client.ebi.heap = mEBIHeap; - client.reg.heap = mREGHeap; - index = mClients.add(pid, client); - } - Client& client(mClients.editValueAt(index)); - client.createClientHeaps(); - return client; -} - -// ---------------------------------------------------------------------------- -// for debugging / testing ... - -sp<SimpleBestFitAllocator> GPUHardware::getAllocator() const { - Mutex::Autolock _l(mLock); - return mAllocator; -} - -void GPUHardware::unconditionalRevoke() -{ - Mutex::Autolock _l(mLock); - releaseLocked(); -} - -// --------------------------------------------------------------------------- - -sp<IMemory> GPUHardware::GPUArea::map() { - sp<IMemory> memory; - if (clientHeap != 0 && heap != 0) { - memory = clientHeap->mapMemory(0, heap->virtualSize()); - } - return memory; -} - -void GPUHardware::Client::createClientHeaps() -{ - if (smi.clientHeap == 0) - smi.clientHeap = smi.heap->createClientHeap(); - if (ebi.clientHeap == 0) - ebi.clientHeap = ebi.heap->createClientHeap(); - if (reg.clientHeap == 0) - reg.clientHeap = reg.heap->createClientHeap(); -} - -void GPUHardware::Client::revokeAllHeaps() -{ - if (smi.clientHeap != 0) - smi.clientHeap->revoke(); - if (ebi.clientHeap != 0) - ebi.clientHeap->revoke(); - if (reg.clientHeap != 0) - reg.clientHeap->revoke(); -} - -void GPUHardware::registerCallbackLocked(const sp<IGPUCallback>& callback, - Client& client) -{ - sp<IBinder> binder = callback->asBinder(); - if (mRegisteredClients.add(binder, client.pid) >= 0) { - binder->linkToDeath(this); - } -} - -void GPUHardware::binderDied(const wp<IBinder>& who) -{ - Mutex::Autolock _l(mLock); - pid_t pid = mRegisteredClients.valueFor(who); - if (pid != 0) { - ssize_t index = mClients.indexOfKey(pid); - if (index >= 0) { - //LOGD("*** removing client at %d", index); - Client& client(mClients.editValueAt(index)); - client.revokeAllHeaps(); // not really needed in theory - mClients.removeItemsAt(index); - if (mClients.size() == 0) { - //LOGD("*** was last client closing everything"); - mCallback.clear(); - mAllocator.clear(); - mCurrentAllocator.clear(); - mSMIHeap.clear(); - mREGHeap.clear(); - - // NOTE: we cannot clear the EBI heap because surfaceflinger - // itself may be using it, since this is where surfaces - // are allocated. if we're in the middle of compositing - // a surface (even if its process just died), we cannot - // rip the heap under our feet. - - mOwner = NO_OWNER; - } - } - } -} - -// --------------------------------------------------------------------------- - -sp<GPUHardwareInterface> GPUFactory::getGPU() -{ - return new GPUHardware(); -} - -// --------------------------------------------------------------------------- -}; // namespace android - diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.h b/libs/surfaceflinger/GPUHardware/GPUHardware.h deleted file mode 100644 index 3354528..0000000 --- a/libs/surfaceflinger/GPUHardware/GPUHardware.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_GPU_HARDWARE_H -#define ANDROID_GPU_HARDWARE_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/RefBase.h> -#include <utils/threads.h> -#include <utils/KeyedVector.h> - -#include <ui/ISurfaceComposer.h> - -namespace android { - -// --------------------------------------------------------------------------- - -class IGPUCallback; - -class GPUHardwareInterface : public virtual RefBase -{ -public: - virtual void revoke(int pid) = 0; - virtual sp<MemoryDealer> request(int pid) = 0; - virtual status_t request(int pid, const sp<IGPUCallback>& callback, - ISurfaceComposer::gpu_info_t* gpu) = 0; - - virtual status_t friendlyRevoke() = 0; - - // used for debugging only... - virtual sp<SimpleBestFitAllocator> getAllocator() const = 0; - virtual pid_t getOwner() const = 0; - virtual void unconditionalRevoke() = 0; -}; - -// --------------------------------------------------------------------------- - -class GPUFactory -{ -public: - // the gpu factory - static sp<GPUHardwareInterface> getGPU(); -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_GPU_HARDWARE_H diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp deleted file mode 100644 index f65d669..0000000 --- a/libs/surfaceflinger/Layer.cpp +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <cutils/properties.h> - -#include <utils/Errors.h> -#include <utils/Log.h> -#include <utils/StopWatch.h> - -#include <ui/PixelFormat.h> -#include <ui/EGLDisplaySurface.h> - -#include "clz.h" -#include "Layer.h" -#include "LayerBitmap.h" -#include "SurfaceFlinger.h" -#include "VRamHeap.h" -#include "DisplayHardware/DisplayHardware.h" - - -#define DEBUG_RESIZE 0 - - -namespace android { - -// --------------------------------------------------------------------------- - -const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4; -const char* const Layer::typeID = "Layer"; - -// --------------------------------------------------------------------------- - -Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i) - : LayerBaseClient(flinger, display, c, i), - mSecure(false), - mFrontBufferIndex(1), - mNeedsBlending(true), - mResizeTransactionDone(false), - mTextureName(-1U), mTextureWidth(0), mTextureHeight(0) -{ - // no OpenGL operation is possible here, since we might not be - // in the OpenGL thread. -} - -Layer::~Layer() -{ - client->free(clientIndex()); - // this should always be called from the OpenGL thread - if (mTextureName != -1U) { - //glDeleteTextures(1, &mTextureName); - deletedTextures.add(mTextureName); - } -} - -void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags) -{ - LayerBase::initStates(w,h,flags); - - if (flags & ISurfaceComposer::eDestroyBackbuffer) - lcblk->flags |= eNoCopyBack; -} - -sp<LayerBaseClient::Surface> Layer::getSurface() const -{ - return mSurface; -} - -status_t Layer::setBuffers( Client* client, - uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags) -{ - PixelFormatInfo info; - status_t err = getPixelFormatInfo(format, &info); - if (err) return err; - - // TODO: if eHardware is explicitly requested, we should fail - // on systems where we can't allocate memory that can be used with - // DMA engines for instance. - - // FIXME: we always ask for hardware for now (this should come from copybit) - flags |= ISurfaceComposer::eHardware; - - const uint32_t memory_flags = flags & - (ISurfaceComposer::eGPU | - ISurfaceComposer::eHardware | - ISurfaceComposer::eSecure); - - // pixel-alignment. the final alignment may be bigger because - // we always force a 4-byte aligned bpr. - uint32_t alignment = 1; - - if (flags & ISurfaceComposer::eGPU) { - // FIXME: this value should come from the h/w - alignment = 8; - // FIXME: this is msm7201A specific, as its GPU only supports - // BGRA_8888. - if (format == PIXEL_FORMAT_RGBA_8888) { - format = PIXEL_FORMAT_BGRA_8888; - } - } - - mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; - mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; - sp<MemoryDealer> allocators[2]; - for (int i=0 ; i<2 ; i++) { - allocators[i] = client->createAllocator(memory_flags); - if (allocators[i] == 0) - return NO_MEMORY; - mBuffers[i].init(allocators[i]); - int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS); - if (err != NO_ERROR) - return err; - mBuffers[i].clear(); // clear the bits for security - mBuffers[i].getInfo(lcblk->surface + i); - } - - mSurface = new Surface(clientIndex(), - allocators[0]->getMemoryHeap(), - allocators[1]->getMemoryHeap(), - mIdentity); - - return NO_ERROR; -} - -void Layer::reloadTexture(const Region& dirty) -{ - if (UNLIKELY(mTextureName == -1U)) { - // create the texture name the first time - // can't do that in the ctor, because it runs in another thread. - mTextureName = createTexture(); - } - const GGLSurface& t(frontBuffer().surface()); - loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight); -} - - -void Layer::onDraw(const Region& clip) const -{ - if (UNLIKELY(mTextureName == -1LU)) { - //LOGW("Layer %p doesn't have a texture", this); - // the texture has not been created yet, this Layer has - // in fact never been drawn into. this happens frequently with - // SurfaceView. - clearWithOpenGL(clip); - return; - } - - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const LayerBitmap& front(frontBuffer()); - const GGLSurface& t(front.surface()); - - status_t err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - // StopWatch watch("copybit"); - const State& s(drawingState()); - - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - - copybit_image_t src; - front.getBitmapSurface(&src); - copybit_rect_t srect = { 0, 0, t.width, t.height }; - - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation()); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, - s.flags & ISurfaceComposer::eLayerDither ? - COPYBIT_ENABLE : COPYBIT_DISABLE); - - region_iterator it(clip); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!can_use_copybit || err) { - drawWithOpenGL(clip, mTextureName, t); - } -} - -status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h) -{ - LOGD_IF(DEBUG_RESIZE, - "reallocateBuffer (layer=%p), " - "requested (%dx%d), " - "index=%d, (%dx%d), (%dx%d)", - this, - int(w), int(h), - int(index), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); - - status_t err = mBuffers[index].resize(w, h); - if (err == NO_ERROR) { - mBuffers[index].getInfo(lcblk->surface + index); - } else { - LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s", - index, w, h, err, strerror(err)); - // XXX: what to do, what to do? We could try to free some - // hidden surfaces, instead of killing this one? - } - return err; -} - -uint32_t Layer::doTransaction(uint32_t flags) -{ - const Layer::State& front(drawingState()); - const Layer::State& temp(currentState()); - - // the test front.{w|h} != temp.{w|h} is not enough because it is possible - // that the size changed back to its previous value before the buffer - // was resized (in the eLocked case below), in which case, we still - // need to execute the code below so the clients have a chance to be - // release. resze() deals with the fact that the size can be the same. - - /* - * Various states we could be in... - - resize = state & eResizeRequested; - if (backbufferChanged) { - if (resize == 0) { - // ERROR, the resized buffer doesn't have its resize flag set - } else if (resize == mask) { - // ERROR one of the buffer has already been resized - } else if (resize == mask ^ eResizeRequested) { - // ERROR, the resized buffer doesn't have its resize flag set - } else if (resize == eResizeRequested) { - // OK, Normal case, proceed with resize - } - } else { - if (resize == 0) { - // OK, nothing special, do nothing - } else if (resize == mask) { - // restarted transaction, do nothing - } else if (resize == mask ^ eResizeRequested) { - // restarted transaction, do nothing - } else if (resize == eResizeRequested) { - // OK, size reset to previous value, proceed with resize - } - } - */ - - // Index of the back buffer - const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h); - const uint32_t state = lcblk->swapState; - const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state); - const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0; - uint32_t resizeFlags = state & eResizeRequested; - - if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) { - LOGE( "backbuffer size changed, but both resize flags are not set! " - "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), " - "index=%d, (%dx%d), (%dx%d)", - this, state, - int(temp.w), int(temp.h), - int(drawingState().w), int(drawingState().h), - int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); - // if we get there we're pretty screwed. the only reasonable - // thing to do is to pretend we should do the resize since - // backbufferChanged is set (this also will give a chance to - // client to get unblocked) - resizeFlags = eResizeRequested; - } - - if (resizeFlags == eResizeRequested) { - // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex - // here, would be wrong and misleading because by this point - // mFrontBufferIndex has not been updated yet. - - LOGD_IF(DEBUG_RESIZE, - "resize (layer=%p), state=%08x, " - "requested (%dx%d), " - "drawing (%d,%d), " - "index=%d, (%dx%d), (%dx%d)", - this, state, - int(temp.w), int(temp.h), - int(drawingState().w), int(drawingState().h), - int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); - - if (state & eLocked) { - // if the buffer is locked, we can't resize anything because - // - the backbuffer is currently in use by the user - // - the front buffer is being shown - // We just act as if the transaction didn't happen and we - // reschedule it later... - flags |= eRestartTransaction; - } else { - // This buffer needs to be resized - status_t err = - resize(clientBackBufferIndex, temp.w, temp.h, "transaction"); - if (err == NO_ERROR) { - const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0; - android_atomic_and(~mask, &(lcblk->swapState)); - // since a buffer became available, we can let the client go... - mFlinger->scheduleBroadcast(client); - mResizeTransactionDone = true; - - // we're being resized and there is a freeze display request, - // acquire a freeze lock, so that the screen stays put - // until we've redrawn at the new size; this is to avoid - // glitches upon orientation changes. - if (mFlinger->hasFreezeRequest()) { - // if the surface is hidden, don't try to acquire the - // freeze lock, since hidden surfaces may never redraw - if (!(front.flags & ISurfaceComposer::eLayerHidden)) { - mFreezeLock = mFlinger->getFreezeLock(); - } - } - } - } - } - - if (temp.sequence != front.sequence) { - if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) { - // this surface is now hidden, so it shouldn't hold a freeze lock - // (it may never redraw, which is fine if it is hidden) - mFreezeLock.clear(); - } - } - - return LayerBase::doTransaction(flags); -} - -status_t Layer::resize( - int32_t clientBackBufferIndex, - uint32_t width, uint32_t height, - const char* what) -{ - /* - * handle resize (backbuffer and frontbuffer reallocation) - */ - - const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]); - - // if the new (transaction) size is != from the the backbuffer - // then we need to reallocate the backbuffer - bool backbufferChanged = (clientBackBuffer.width() != width) || - (clientBackBuffer.height() != height); - - LOGD_IF(!backbufferChanged, - "(%s) eResizeRequested (layer=%p), but size not changed: " - "requested (%dx%d), drawing (%d,%d), current (%d,%d)," - "state=%08lx, index=%d, (%dx%d), (%dx%d)", - what, this, - int(width), int(height), - int(drawingState().w), int(drawingState().h), - int(currentState().w), int(currentState().h), - long(lcblk->swapState), - int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); - - // this can happen when changing the size back and forth quickly - status_t err = NO_ERROR; - if (backbufferChanged) { - err = reallocateBuffer(clientBackBufferIndex, width, height); - } - if (UNLIKELY(err != NO_ERROR)) { - // couldn't reallocate the surface - android_atomic_write(eInvalidSurface, &lcblk->swapState); - memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t)); - } - return err; -} - -void Layer::setSizeChanged(uint32_t w, uint32_t h) -{ - LOGD_IF(DEBUG_RESIZE, - "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)", - w, h, mCurrentState.w, mCurrentState.h); - android_atomic_or(eResizeRequested, &(lcblk->swapState)); -} - -// ---------------------------------------------------------------------------- -// pageflip handling... -// ---------------------------------------------------------------------------- - -void Layer::lockPageFlip(bool& recomputeVisibleRegions) -{ - uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState)); - // preemptively block the client, because he might set - // eFlipRequested at any time and want to use this buffer - // for the next frame. This will be unset below if it - // turns out we didn't need it. - - uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested; - if (!(state & mask)) - return; - - if (UNLIKELY(state & eInvalidSurface)) { - // if eInvalidSurface is set, this means the surface - // became invalid during a transaction (NO_MEMORY for instance) - mFlinger->scheduleBroadcast(client); - return; - } - - if (UNLIKELY(state & eFlipRequested)) { - uint32_t oldState; - mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions); - if (oldState & eNextFlipPending) { - // Process another round (we know at least a buffer - // is ready for that client). - mFlinger->signalEvent(); - } - } -} - -Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) -{ - // atomically swap buffers and (re)set eFlipRequested - int32_t oldValue, newValue; - layer_cblk_t * const lcblk = this->lcblk; - do { - oldValue = lcblk->swapState; - // get the current value - - LOG_ASSERT(oldValue&eFlipRequested, - "eFlipRequested not set, yet we're flipping! (state=0x%08lx)", - long(oldValue)); - - newValue = (oldValue ^ eIndex); - // swap buffers - - newValue &= ~(eFlipRequested | eNextFlipPending); - // clear eFlipRequested and eNextFlipPending - - if (oldValue & eNextFlipPending) - newValue |= eFlipRequested; - // if eNextFlipPending is set (second buffer already has something - // in it) we need to reset eFlipRequested because the client - // might never do it - - } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState))); - *previousSate = oldValue; - - const int32_t index = (newValue & eIndex) ^ 1; - mFrontBufferIndex = index; - - // ... post the new front-buffer - Region dirty(lcblk->region + index); - dirty.andSelf(frontBuffer().bounds()); - - //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n", - // oldValue, newValue, mFrontBufferIndex); - //dirty.dump("dirty"); - - if (UNLIKELY(oldValue & eResizeRequested)) { - - LOGD_IF(DEBUG_RESIZE, - "post (layer=%p), state=%08x, " - "index=%d, (%dx%d), (%dx%d)", - this, newValue, - int(1-index), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); - - // here, we just posted the surface and we have resolved - // the front/back buffer indices. The client is blocked, so - // it cannot start using the new backbuffer. - - // If the backbuffer was resized in THIS round, we actually cannot - // resize the frontbuffer because it has *just* been drawn (and we - // would have nothing to draw). In this case we just skip the resize - // it'll happen after the next page flip or during the next - // transaction. - - const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0; - if (mResizeTransactionDone && (newValue & mask)) { - // Resize the layer's second buffer only if the transaction - // happened. It may not have happened yet if eResizeRequested - // was set immediately after the "transactionRequested" test, - // in which case the drawing state's size would be wrong. - mFreezeLock.clear(); - const Layer::State& s(drawingState()); - if (resize(1-index, s.w, s.h, "post") == NO_ERROR) { - do { - oldValue = lcblk->swapState; - if ((oldValue & eResizeRequested) == eResizeRequested) { - // ugh, another resize was requested since we processed - // the first buffer, don't free the client, and let - // the next transaction handle everything. - break; - } - newValue = oldValue & ~mask; - } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState))); - } - mResizeTransactionDone = false; - recomputeVisibleRegions = true; - this->contentDirty = true; - } - } - - reloadTexture(dirty); - - return dirty; -} - -Point Layer::getPhysicalSize() const -{ - const LayerBitmap& front(frontBuffer()); - return Point(front.width(), front.height()); -} - -void Layer::unlockPageFlip( - const Transform& planeTransform, Region& outDirtyRegion) -{ - Region dirtyRegion(mPostedDirtyRegion); - if (!dirtyRegion.isEmpty()) { - mPostedDirtyRegion.clear(); - // The dirty region is given in the layer's coordinate space - // transform the dirty region by the surface's transformation - // and the global transformation. - const Layer::State& s(drawingState()); - const Transform tr(planeTransform * s.transform); - dirtyRegion = tr.transform(dirtyRegion); - - // At this point, the dirty region is in screen space. - // Make sure it's constrained by the visible region (which - // is in screen space as well). - dirtyRegion.andSelf(visibleRegionScreen); - outDirtyRegion.orSelf(dirtyRegion); - - // client could be blocked, so signal them so they get a - // chance to reevaluate their condition. - mFlinger->scheduleBroadcast(client); - } -} - -void Layer::finishPageFlip() -{ - if (LIKELY(!(lcblk->swapState & eInvalidSurface))) { - LOGE_IF(!(lcblk->swapState & eBusy), - "layer %p wasn't locked!", this); - android_atomic_and(~eBusy, &(lcblk->swapState)); - } - mFlinger->scheduleBroadcast(client); -} - - -// --------------------------------------------------------------------------- - - -}; // namespace android diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h deleted file mode 100644 index 2867f2b..0000000 --- a/libs/surfaceflinger/Layer.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_H -#define ANDROID_LAYER_H - -#include <stdint.h> -#include <sys/types.h> - -#include <ui/PixelFormat.h> - -#include <private/ui/SharedState.h> -#include <private/ui/LayerState.h> - -#include <pixelflinger/pixelflinger.h> - -#include "LayerBitmap.h" -#include "LayerBase.h" -#include "Transform.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class Client; -class LayerBitmap; -class MemoryDealer; -class FreezeLock; - -// --------------------------------------------------------------------------- - -class Layer : public LayerBaseClient -{ -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - Layer(SurfaceFlinger* flinger, DisplayID display, - Client* c, int32_t i); - - virtual ~Layer(); - - inline PixelFormat pixelFormat() const { - return frontBuffer().pixelFormat(); - } - - status_t setBuffers( Client* client, - uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags=0); - - virtual void onDraw(const Region& clip) const; - virtual void initStates(uint32_t w, uint32_t h, uint32_t flags); - virtual void setSizeChanged(uint32_t w, uint32_t h); - virtual uint32_t doTransaction(uint32_t transactionFlags); - virtual Point getPhysicalSize() const; - virtual void lockPageFlip(bool& recomputeVisibleRegions); - virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); - virtual void finishPageFlip(); - virtual bool needsBlending() const { return mNeedsBlending; } - virtual bool isSecure() const { return mSecure; } - virtual GLuint getTextureName() const { return mTextureName; } - virtual sp<Surface> getSurface() const; - - const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; } - LayerBitmap& getBuffer(int i) { return mBuffers[i]; } - - // only for debugging - const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; } - -private: - inline const LayerBitmap& - frontBuffer() const { return getBuffer(mFrontBufferIndex); } - inline LayerBitmap& - frontBuffer() { return getBuffer(mFrontBufferIndex); } - inline const LayerBitmap& - backBuffer() const { return getBuffer(1-mFrontBufferIndex); } - inline LayerBitmap& - backBuffer() { return getBuffer(1-mFrontBufferIndex); } - - void reloadTexture(const Region& dirty); - - status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what); - Region post(uint32_t* oldState, bool& recomputeVisibleRegions); - status_t reallocateBuffer(int32_t index, uint32_t w, uint32_t h); - - sp<Surface> mSurface; - - bool mSecure; - LayerBitmap mBuffers[2]; - int32_t mFrontBufferIndex; - bool mNeedsBlending; - bool mResizeTransactionDone; - Region mPostedDirtyRegion; - sp<FreezeLock> mFreezeLock; - - GLuint mTextureName; - GLuint mTextureWidth; - GLuint mTextureHeight; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_H diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp deleted file mode 100644 index 0cf53f7..0000000 --- a/libs/surfaceflinger/LayerBase.cpp +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <GLES/gl.h> -#include <GLES/glext.h> - -#include <hardware/hardware.h> - -#include "clz.h" -#include "LayerBase.h" -#include "LayerBlur.h" -#include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" - - -// We don't honor the premultiplied alpha flags, which means that -// premultiplied surface may be composed using a non-premultiplied -// equation. We do this because it may be a lot faster on some hardware -// The correct value is HONOR_PREMULTIPLIED_ALPHA = 1 -#define HONOR_PREMULTIPLIED_ALPHA 0 - -namespace android { - -// --------------------------------------------------------------------------- - -const uint32_t LayerBase::typeInfo = 1; -const char* const LayerBase::typeID = "LayerBase"; - -const uint32_t LayerBaseClient::typeInfo = LayerBase::typeInfo | 2; -const char* const LayerBaseClient::typeID = "LayerBaseClient"; - -// --------------------------------------------------------------------------- - -Vector<GLuint> LayerBase::deletedTextures; - -int32_t LayerBase::sIdentity = 0; - -LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) - : dpy(display), contentDirty(false), - mFlinger(flinger), - mTransformed(false), - mOrientation(0), - mCanUseCopyBit(false), - mTransactionFlags(0), - mPremultipliedAlpha(true), - mIdentity(uint32_t(android_atomic_inc(&sIdentity))), - mInvalidate(0) -{ - const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); - mFlags = hw.getFlags(); -} - -LayerBase::~LayerBase() -{ -} - -const GraphicPlane& LayerBase::graphicPlane(int dpy) const -{ - return mFlinger->graphicPlane(dpy); -} - -GraphicPlane& LayerBase::graphicPlane(int dpy) -{ - return mFlinger->graphicPlane(dpy); -} - -void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags) -{ - uint32_t layerFlags = 0; - if (flags & ISurfaceComposer::eHidden) - layerFlags = ISurfaceComposer::eLayerHidden; - - if (flags & ISurfaceComposer::eNonPremultiplied) - mPremultipliedAlpha = false; - - mCurrentState.z = 0; - mCurrentState.w = w; - mCurrentState.h = h; - mCurrentState.alpha = 0xFF; - mCurrentState.flags = layerFlags; - mCurrentState.sequence = 0; - mCurrentState.transform.set(0, 0); - - // drawing state & current state are identical - mDrawingState = mCurrentState; -} - -void LayerBase::commitTransaction(bool skipSize) { - const uint32_t w = mDrawingState.w; - const uint32_t h = mDrawingState.h; - mDrawingState = mCurrentState; - if (skipSize) { - mDrawingState.w = w; - mDrawingState.h = h; - } -} -void LayerBase::forceVisibilityTransaction() { - // this can be called without SurfaceFlinger.mStateLock, but if we - // can atomically increment the sequence number, it doesn't matter. - android_atomic_inc(&mCurrentState.sequence); - requestTransaction(); -} -bool LayerBase::requestTransaction() { - int32_t old = setTransactionFlags(eTransactionNeeded); - return ((old & eTransactionNeeded) == 0); -} -uint32_t LayerBase::getTransactionFlags(uint32_t flags) { - return android_atomic_and(~flags, &mTransactionFlags) & flags; -} -uint32_t LayerBase::setTransactionFlags(uint32_t flags) { - return android_atomic_or(flags, &mTransactionFlags); -} - -void LayerBase::setSizeChanged(uint32_t w, uint32_t h) { -} - -bool LayerBase::setPosition(int32_t x, int32_t y) { - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) - return false; - mCurrentState.sequence++; - mCurrentState.transform.set(x, y); - requestTransaction(); - return true; -} -bool LayerBase::setLayer(uint32_t z) { - if (mCurrentState.z == z) - return false; - mCurrentState.sequence++; - mCurrentState.z = z; - requestTransaction(); - return true; -} -bool LayerBase::setSize(uint32_t w, uint32_t h) { - if (mCurrentState.w == w && mCurrentState.h == h) - return false; - setSizeChanged(w, h); - mCurrentState.w = w; - mCurrentState.h = h; - requestTransaction(); - return true; -} -bool LayerBase::setAlpha(uint8_t alpha) { - if (mCurrentState.alpha == alpha) - return false; - mCurrentState.sequence++; - mCurrentState.alpha = alpha; - requestTransaction(); - return true; -} -bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) { - // TODO: check the matrix has changed - mCurrentState.sequence++; - mCurrentState.transform.set( - matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy); - requestTransaction(); - return true; -} -bool LayerBase::setTransparentRegionHint(const Region& transparent) { - // TODO: check the region has changed - mCurrentState.sequence++; - mCurrentState.transparentRegion = transparent; - requestTransaction(); - return true; -} -bool LayerBase::setFlags(uint8_t flags, uint8_t mask) { - const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); - if (mCurrentState.flags == newFlags) - return false; - mCurrentState.sequence++; - mCurrentState.flags = newFlags; - requestTransaction(); - return true; -} - -Rect LayerBase::visibleBounds() const -{ - return mTransformedBounds; -} - -void LayerBase::setVisibleRegion(const Region& visibleRegion) { - // always called from main thread - visibleRegionScreen = visibleRegion; -} - -void LayerBase::setCoveredRegion(const Region& coveredRegion) { - // always called from main thread - coveredRegionScreen = coveredRegion; -} - -uint32_t LayerBase::doTransaction(uint32_t flags) -{ - const Layer::State& front(drawingState()); - const Layer::State& temp(currentState()); - - if (temp.sequence != front.sequence) { - // invalidate and recompute the visible regions if needed - flags |= eVisibleRegion; - this->contentDirty = true; - } - - // Commit the transaction - commitTransaction(flags & eRestartTransaction); - return flags; -} - -Point LayerBase::getPhysicalSize() const -{ - const Layer::State& front(drawingState()); - return Point(front.w, front.h); -} - -void LayerBase::validateVisibility(const Transform& planeTransform) -{ - const Layer::State& s(drawingState()); - const Transform tr(planeTransform * s.transform); - const bool transformed = tr.transformed(); - - const Point size(getPhysicalSize()); - uint32_t w = size.x; - uint32_t h = size.y; - tr.transform(mVertices[0], 0, 0); - tr.transform(mVertices[1], 0, h); - tr.transform(mVertices[2], w, h); - tr.transform(mVertices[3], w, 0); - if (UNLIKELY(transformed)) { - // NOTE: here we could also punt if we have too many rectangles - // in the transparent region - if (tr.preserveRects()) { - // transform the transparent region - transparentRegionScreen = tr.transform(s.transparentRegion); - } else { - // transformation too complex, can't do the transparent region - // optimization. - transparentRegionScreen.clear(); - } - } else { - transparentRegionScreen = s.transparentRegion; - } - - // cache a few things... - mOrientation = tr.getOrientation(); - mTransformedBounds = tr.makeBounds(w, h); - mTransformed = transformed; - mLeft = tr.tx(); - mTop = tr.ty(); - - // see if we can/should use 2D h/w with the new configuration - mCanUseCopyBit = false; - copybit_device_t* copybit = mFlinger->getBlitEngine(); - if (copybit) { - const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG); - const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS); - mCanUseCopyBit = true; - if ((mOrientation < 0) && (step > 1)) { - // arbitrary orientations not supported - mCanUseCopyBit = false; - } else if ((mOrientation > 0) && (step > 90)) { - // 90 deg rotations not supported - mCanUseCopyBit = false; - } else if ((tr.getType() & SkMatrix::kScale_Mask) && (scaleBits < 12)) { - // arbitrary scaling not supported - mCanUseCopyBit = false; - } -#if HONOR_PREMULTIPLIED_ALPHA - else if (needsBlending() && mPremultipliedAlpha) { - // pre-multiplied alpha not supported - mCanUseCopyBit = false; - } -#endif - else { - // here, we determined we can use copybit - if (tr.getType() & SkMatrix::kScale_Mask) { - // and we have scaling - if (!transparentRegionScreen.isRect()) { - // we punt because blending is cheap (h/w) and the region is - // complex, which may causes artifacts when copying - // scaled content - transparentRegionScreen.clear(); - } - } - } - } -} - -void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) -{ -} - -void LayerBase::unlockPageFlip( - const Transform& planeTransform, Region& outDirtyRegion) -{ - if ((android_atomic_and(~1, &mInvalidate)&1) == 1) { - outDirtyRegion.orSelf(visibleRegionScreen); - } -} - -void LayerBase::finishPageFlip() -{ -} - -void LayerBase::invalidate() -{ - if ((android_atomic_or(1, &mInvalidate)&1) == 0) { - mFlinger->signalEvent(); - } -} - -void LayerBase::drawRegion(const Region& reg) const -{ - Region::iterator iterator(reg); - if (iterator) { - Rect r; - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const int32_t fbWidth = hw.getWidth(); - const int32_t fbHeight = hw.getHeight(); - const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, - { fbWidth, fbHeight }, { 0, fbHeight } }; - glVertexPointer(2, GL_SHORT, 0, vertices); - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - } -} - -void LayerBase::draw(const Region& inClip) const -{ - // invalidate the region we'll update - Region clip(inClip); // copy-on-write, so no-op most of the time - - // Remove the transparent area from the clipping region - const State& s = drawingState(); - if (LIKELY(!s.transparentRegion.isEmpty())) { - clip.subtract(transparentRegionScreen); - if (clip.isEmpty()) { - // usually this won't happen because this should be taken care of - // by SurfaceFlinger::computeVisibleRegions() - return; - } - } - - // reset GL state - glEnable(GL_SCISSOR_TEST); - - onDraw(clip); - - /* - glDisable(GL_TEXTURE_2D); - glDisable(GL_DITHER); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4x(0, 0x8000, 0, 0x10000); - drawRegion(transparentRegionScreen); - glDisable(GL_BLEND); - */ -} - -GLuint LayerBase::createTexture() const -{ - GLuint textureName = -1; - glGenTextures(1, &textureName); - glBindTexture(GL_TEXTURE_2D, textureName); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (mFlags & DisplayHardware::SLOW_CONFIG) { - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } else { - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - return textureName; -} - -void LayerBase::clearWithOpenGL(const Region& clip) const -{ - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const uint32_t fbHeight = hw.getHeight(); - glColor4x(0,0,0,0); - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - glDisable(GL_DITHER); - Rect r; - Region::iterator iterator(clip); - if (iterator) { - glEnable(GL_SCISSOR_TEST); - glVertexPointer(2, GL_FIXED, 0, mVertices); - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - } -} - -void LayerBase::drawWithOpenGL(const Region& clip, - GLint textureName, const GGLSurface& t, int transform) const -{ - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const uint32_t fbHeight = hw.getHeight(); - const State& s(drawingState()); - - // bind our texture - validateTexture(textureName); - glEnable(GL_TEXTURE_2D); - - // Dithering... - if (s.flags & ISurfaceComposer::eLayerDither) { - glEnable(GL_DITHER); - } else { - glDisable(GL_DITHER); - } - - if (UNLIKELY(s.alpha < 0xFF)) { - // We have an alpha-modulation. We need to modulate all - // texture components by alpha because we're always using - // premultiplied alpha. - - // If the texture doesn't have an alpha channel we can - // use REPLACE and switch to non premultiplied alpha - // blending (SRCA/ONE_MINUS_SRCA). - - GLenum env, src; - if (needsBlending()) { - env = GL_MODULATE; - src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; - } else { - env = GL_REPLACE; - src = GL_SRC_ALPHA; - } - const GGLfixed alpha = (s.alpha << 16)/255; - glColor4x(alpha, alpha, alpha, alpha); - glEnable(GL_BLEND); - glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env); - } else { - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glColor4x(0x10000, 0x10000, 0x10000, 0x10000); - if (needsBlending()) { - GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; - glEnable(GL_BLEND); - glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); - } else { - glDisable(GL_BLEND); - } - } - - if (UNLIKELY(transformed() - || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) - { - //StopWatch watch("GL transformed"); - Region::iterator iterator(clip); - if (iterator) { - // always use high-quality filtering with fast configurations - bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG); - if (!fast && s.flags & ISurfaceComposer::eLayerFilter) { - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - const GLfixed texCoords[4][2] = { - { 0, 0 }, - { 0, 0x10000 }, - { 0x10000, 0x10000 }, - { 0x10000, 0 } - }; - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - - if (transform == HAL_TRANSFORM_ROT_90) { - glTranslatef(0, 1, 0); - glRotatef(-90, 0, 0, 1); - } - - if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { - // find the smallest power-of-two that will accommodate our surface - GLuint tw = 1 << (31 - clz(t.width)); - GLuint th = 1 << (31 - clz(t.height)); - if (tw < t.width) tw <<= 1; - if (th < t.height) th <<= 1; - // this divide should be relatively fast because it's - // a power-of-two (optimized path in libgcc) - GLfloat ws = GLfloat(t.width) /tw; - GLfloat hs = GLfloat(t.height)/th; - glScalef(ws, hs, 1.0f); - } - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FIXED, 0, mVertices); - glTexCoordPointer(2, GL_FIXED, 0, texCoords); - - Rect r; - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - - if (!fast && s.flags & ISurfaceComposer::eLayerFilter) { - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - } else { - Region::iterator iterator(clip); - if (iterator) { - Rect r; - GLint crop[4] = { 0, t.height, t.width, -t.height }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - int x = tx(); - int y = ty(); - y = fbHeight - (y + t.height); - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, t.width, t.height); - } - } - } -} - -void LayerBase::validateTexture(GLint textureName) const -{ - glBindTexture(GL_TEXTURE_2D, textureName); - // TODO: reload the texture if needed - // this is currently done in loadTexture() below -} - -void LayerBase::loadTexture(const Region& dirty, - GLint textureName, const GGLSurface& t, - GLuint& textureWidth, GLuint& textureHeight) const -{ - // TODO: defer the actual texture reload until LayerBase::validateTexture - // is called. - - uint32_t flags = mFlags; - glBindTexture(GL_TEXTURE_2D, textureName); - - GLuint tw = t.width; - GLuint th = t.height; - - /* - * In OpenGL ES we can't specify a stride with glTexImage2D (however, - * GL_UNPACK_ALIGNMENT is 4, which in essence allows a limited form of - * stride). - * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we - * need to do something reasonable (here creating a bigger texture). - * - * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT); - * - * This situation doesn't happen often, but some h/w have a limitation - * for their framebuffer (eg: must be multiple of 8 pixels), and - * we need to take that into account when using these buffers as - * textures. - * - * This should never be a problem with POT textures - */ - - tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4); - - /* - * round to POT if needed - */ - - GLuint texture_w = tw; - GLuint texture_h = th; - if (!(flags & DisplayHardware::NPOT_EXTENSION)) { - // find the smallest power-of-two that will accommodate our surface - texture_w = 1 << (31 - clz(t.width)); - texture_h = 1 << (31 - clz(t.height)); - if (texture_w < t.width) texture_w <<= 1; - if (texture_h < t.height) texture_h <<= 1; - if (texture_w != tw || texture_h != th) { - // we can't use DIRECT_TEXTURE since we changed the size - // of the texture - flags &= ~DisplayHardware::DIRECT_TEXTURE; - } - } - - if (flags & DisplayHardware::DIRECT_TEXTURE) { - // here we're guaranteed that texture_{w|h} == t{w|h} - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGB, tw, th, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_BYTE, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) { - // TODO: add GL_BGRA extension - } else { - // oops, we don't handle this format, try the regular path - goto regular; - } - textureWidth = tw; - textureHeight = th; - } else { -regular: - Rect bounds(dirty.bounds()); - GLvoid* data = 0; - if (texture_w!=textureWidth || texture_h!=textureHeight) { - // texture size changed, we need to create a new one - - if (!textureWidth || !textureHeight) { - // this is the first time, load the whole texture - if (texture_w==tw && texture_h==th) { - // we can do it one pass - data = t.data; - } else { - // we have to create the texture first because it - // doesn't match the size of the buffer - bounds.set(Rect(tw, th)); - } - } - - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGB, texture_w, texture_h, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, data); - } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || - t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { - // just show the Y plane of YUV buffers - data = t.data; - glTexImage2D(GL_TEXTURE_2D, 0, - GL_LUMINANCE, texture_w, texture_h, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); - } else { - // oops, we don't handle this format! - LOGE("layer %p, texture=%d, using format %d, which is not " - "supported by the GL", this, textureName, t.format); - textureName = -1; - } - textureWidth = texture_w; - textureHeight = texture_h; - } - if (!data && textureName>=0) { - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - t.data + bounds.top*t.width*2); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, - t.data + bounds.top*t.width*2); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_BYTE, - t.data + bounds.top*t.width*4); - } - } - } -} - -bool LayerBase::canUseCopybit() const -{ - return mCanUseCopyBit; -} - -// --------------------------------------------------------------------------- - -LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, - Client* c, int32_t i) - : LayerBase(flinger, display), client(c), - lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ), - mIndex(i) -{ - if (client) { - client->bindLayer(this, i); - - // Initialize this layer's control block - memset(this->lcblk, 0, sizeof(layer_cblk_t)); - this->lcblk->identity = mIdentity; - Region::writeEmpty(&(this->lcblk->region[0]), sizeof(flat_region_t)); - Region::writeEmpty(&(this->lcblk->region[1]), sizeof(flat_region_t)); - } -} - -LayerBaseClient::~LayerBaseClient() -{ - if (client) { - client->free(mIndex); - } -} - -int32_t LayerBaseClient::serverIndex() const { - if (client) { - return (client->cid<<16)|mIndex; - } - return 0xFFFF0000 | mIndex; -} - -sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const -{ - return new Surface(clientIndex(), mIdentity); -} - - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h deleted file mode 100644 index a020f44..0000000 --- a/libs/surfaceflinger/LayerBase.h +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_BASE_H -#define ANDROID_LAYER_BASE_H - -#include <stdint.h> -#include <sys/types.h> - -#include <private/ui/LayerState.h> - -#include <ui/Region.h> -#include <ui/Overlay.h> - -#include <pixelflinger/pixelflinger.h> - -#include "Transform.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class SurfaceFlinger; -class DisplayHardware; -class GraphicPlane; -class Client; - -// --------------------------------------------------------------------------- - -class LayerBase -{ - // poor man's dynamic_cast below - template<typename T> - struct getTypeInfoOfAnyType { - static uint32_t get() { return T::typeInfo; } - }; - - template<typename T> - struct getTypeInfoOfAnyType<T*> { - static uint32_t get() { return getTypeInfoOfAnyType<T>::get(); } - }; - -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - template<typename T> - static T dynamicCast(LayerBase* base) { - uint32_t mostDerivedInfo = base->getTypeInfo(); - uint32_t castToInfo = getTypeInfoOfAnyType<T>::get(); - if ((mostDerivedInfo & castToInfo) == castToInfo) - return static_cast<T>(base); - return 0; - } - - - static Vector<GLuint> deletedTextures; - - LayerBase(SurfaceFlinger* flinger, DisplayID display); - virtual ~LayerBase(); - - DisplayID dpy; - mutable bool contentDirty; - Region visibleRegionScreen; - Region transparentRegionScreen; - Region coveredRegionScreen; - - struct State { - uint32_t w; - uint32_t h; - uint32_t z; - uint8_t alpha; - uint8_t flags; - uint8_t reserved[2]; - int32_t sequence; // changes when visible regions can change - uint32_t tint; - Transform transform; - Region transparentRegion; - }; - - // modify current state - bool setPosition(int32_t x, int32_t y); - bool setLayer(uint32_t z); - bool setSize(uint32_t w, uint32_t h); - bool setAlpha(uint8_t alpha); - bool setMatrix(const layer_state_t::matrix22_t& matrix); - bool setTransparentRegionHint(const Region& opaque); - bool setFlags(uint8_t flags, uint8_t mask); - - void commitTransaction(bool skipSize); - bool requestTransaction(); - void forceVisibilityTransaction(); - - uint32_t getTransactionFlags(uint32_t flags); - uint32_t setTransactionFlags(uint32_t flags); - - Rect visibleBounds() const; - void drawRegion(const Region& reg) const; - - void invalidate(); - - /** - * draw - performs some global clipping optimizations - * and calls onDraw(). - * Typically this method is not overridden, instead implement onDraw() - * to perform the actual drawing. - */ - virtual void draw(const Region& clip) const; - - /** - * onDraw - draws the surface. - */ - virtual void onDraw(const Region& clip) const = 0; - - /** - * initStates - called just after construction - */ - virtual void initStates(uint32_t w, uint32_t h, uint32_t flags); - - /** - * setSizeChanged - called when the *current* state's size is changed. - */ - virtual void setSizeChanged(uint32_t w, uint32_t h); - - /** - * doTransaction - process the transaction. This is a good place to figure - * out which attributes of the surface have changed. - */ - virtual uint32_t doTransaction(uint32_t transactionFlags); - - /** - * setVisibleRegion - called to set the new visible region. This gives - * a chance to update the new visible region or record the fact it changed. - */ - virtual void setVisibleRegion(const Region& visibleRegion); - - /** - * setCoveredRegion - called when the covered region changes. The covered - * region correspond to any area of the surface that is covered - * (transparently or not) by another surface. - */ - virtual void setCoveredRegion(const Region& coveredRegion); - - /** - * getPhysicalSize - returns the physical size of the drawing state of - * the surface. If the surface is backed by a bitmap, this is the size of - * the bitmap (as opposed to the size of the drawing state). - */ - virtual Point getPhysicalSize() const; - - /** - * validateVisibility - cache a bunch of things - */ - virtual void validateVisibility(const Transform& globalTransform); - - /** - * lockPageFlip - called each time the screen is redrawn and returns whether - * the visible regions need to be recomputed (this is a fairly heavy - * operation, so this should be set only if needed). Typically this is used - * to figure out if the content or size of a surface has changed. - */ - virtual void lockPageFlip(bool& recomputeVisibleRegions); - - /** - * unlockPageFlip - called each time the screen is redrawn. updates the - * final dirty region wrt the planeTransform. - * At this point, all visible regions, surface position and size, etc... are - * correct. - */ - virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); - - /** - * finishPageFlip - called after all surfaces have drawn. - */ - virtual void finishPageFlip(); - - /** - * needsBlending - true if this surface needs blending - */ - virtual bool needsBlending() const { return false; } - - /** - * transformed -- true is this surface needs a to be transformed - */ - virtual bool transformed() const { return mTransformed; } - - /** - * isSecure - true if this surface is secure, that is if it prevents - * screenshots or vns servers. - */ - virtual bool isSecure() const { return false; } - - enum { // flags for doTransaction() - eVisibleRegion = 0x00000002, - eRestartTransaction = 0x00000008 - }; - - - inline const State& drawingState() const { return mDrawingState; } - inline const State& currentState() const { return mCurrentState; } - inline State& currentState() { return mCurrentState; } - - static int compareCurrentStateZ(LayerBase*const* layerA, LayerBase*const* layerB) { - return layerA[0]->currentState().z - layerB[0]->currentState().z; - } - - int32_t getOrientation() const { return mOrientation; } - int tx() const { return mLeft; } - int ty() const { return mTop; } - -protected: - const GraphicPlane& graphicPlane(int dpy) const; - GraphicPlane& graphicPlane(int dpy); - - GLuint createTexture() const; - - void drawWithOpenGL(const Region& clip, - GLint textureName, - const GGLSurface& surface, - int transform = 0) const; - - void clearWithOpenGL(const Region& clip) const; - - void loadTexture(const Region& dirty, - GLint textureName, const GGLSurface& t, - GLuint& textureWidth, GLuint& textureHeight) const; - - bool canUseCopybit() const; - - SurfaceFlinger* mFlinger; - uint32_t mFlags; - - // cached during validateVisibility() - bool mTransformed; - int32_t mOrientation; - GLfixed mVertices[4][2]; - Rect mTransformedBounds; - bool mCanUseCopyBit; - int mLeft; - int mTop; - - // these are protected by an external lock - State mCurrentState; - State mDrawingState; - volatile int32_t mTransactionFlags; - - // don't change, don't need a lock - bool mPremultipliedAlpha; - - // only read - const uint32_t mIdentity; - - // atomic - volatile int32_t mInvalidate; - - -private: - void validateTexture(GLint textureName) const; - static int32_t sIdentity; -}; - - -// --------------------------------------------------------------------------- - -class LayerBaseClient : public LayerBase -{ -public: - class Surface; - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, - Client* client, int32_t i); - virtual ~LayerBaseClient(); - - - Client* const client; - layer_cblk_t* const lcblk; - - inline int32_t clientIndex() const { return mIndex; } - int32_t serverIndex() const; - - virtual sp<Surface> getSurface() const; - - uint32_t getIdentity() const { return mIdentity; } - - class Surface : public BnSurface - { - public: - Surface(SurfaceID id, int identity) { - mParams.token = id; - mParams.identity = identity; - } - Surface(SurfaceID id, - const sp<IMemoryHeap>& heap0, - const sp<IMemoryHeap>& heap1, - int identity) - { - mParams.token = id; - mParams.identity = identity; - mParams.heap[0] = heap0; - mParams.heap[1] = heap1; - } - virtual ~Surface() { - // TODO: We now have a point here were we can clean-up the - // client's mess. - // This is also where surface id should be recycled. - //LOGD("Surface %d, heaps={%p, %p} destroyed", - // mId, mHeap[0].get(), mHeap[1].get()); - } - - virtual void getSurfaceData( - ISurfaceFlingerClient::surface_data_t* params) const { - *params = mParams; - } - - virtual status_t registerBuffers(const ISurface::BufferHeap& buffers) - { return INVALID_OPERATION; } - virtual void postBuffer(ssize_t offset) { } - virtual void unregisterBuffers() { }; - virtual sp<OverlayRef> createOverlay( - uint32_t w, uint32_t h, int32_t format) { - return NULL; - }; - - private: - ISurfaceFlingerClient::surface_data_t mParams; - }; - -private: - int32_t mIndex; - -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_BASE_H diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp deleted file mode 100644 index e844350..0000000 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <cutils/memory.h> -#include <utils/Errors.h> -#include <utils/Log.h> -#include <utils/MemoryDealer.h> -#include <utils/IMemory.h> -#include <ui/PixelFormat.h> -#include <pixelflinger/pixelflinger.h> - -#include "LayerBitmap.h" -#include "SurfaceFlinger.h" -#include "VRamHeap.h" - - -namespace android { - -// --------------------------------------------------------------------------- - -LayerBitmap::LayerBitmap() - : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2) -{ - memset(&mSurface, 0, sizeof(mSurface)); -} - -LayerBitmap::~LayerBitmap() -{ - mSurface.data = 0; -} - -status_t LayerBitmap::init(const sp<MemoryDealer>& allocator) -{ - if (mAllocator != NULL) - return BAD_VALUE; - mAllocator = allocator; - return NO_ERROR; -} - -status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags) -{ - const sp<MemoryDealer>& allocator(mAllocator); - if (allocator == NULL) - return NO_INIT; - - if (UNLIKELY(w == mSurface.width && h == mSurface.height && - format == mSurface.format)) - { // same format and size, do nothing. - return NO_ERROR; - } - - PixelFormatInfo info; - getPixelFormatInfo(format, &info); - - uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED; - const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT - const uint32_t Bpp = info.bytesPerPixel; - uint32_t stride = (w + (alignment-1)) & ~(alignment-1); - stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp; - size_t size = info.getScanlineSize(stride) * h; - if (allocFlags & MemoryDealer::PAGE_ALIGNED) { - size_t pagesize = getpagesize(); - size = (size + (pagesize-1)) & ~(pagesize-1); - } - - /* FIXME: we should be able to have a h/v stride because the user of the - * surface might have stride limitation (for instance h/w codecs often do) - */ - int32_t vstride = 0; - - mAlignment = alignment; - mAllocFlags = allocFlags; - mOffset = 0; - if (mSize != size) { - // would be nice to have a reallocate() api - mBitsMemory.clear(); // free-memory - mBitsMemory = allocator->allocate(size, allocFlags); - mSize = size; - } else { - // don't erase memory if we didn't have to reallocate - flags &= ~SECURE_BITS; - } - if (mBitsMemory != 0) { - mOffset = mBitsMemory->offset(); - mSurface.data = static_cast<GGLubyte*>(mBitsMemory->pointer()); - mSurface.version = sizeof(GGLSurface); - mSurface.width = w; - mSurface.height = h; - mSurface.stride = stride; - mSurface.vstride = vstride; - mSurface.format = format; - if (flags & SECURE_BITS) - clear(); - } - - if (mBitsMemory==0 || mSurface.data==0) { - LOGE("not enough memory for layer bitmap size=%u", size); - allocator->dump("LayerBitmap"); - mSurface.data = 0; - mSize = -1U; - return NO_MEMORY; - } - return NO_ERROR; -} - -void LayerBitmap::clear() -{ - // NOTE: this memset should not be necessary, at least for - // opaque surface. However, for security reasons it's better to keep it - // (in the case of pmem, it's possible that the memory contains old - // data) - if (mSurface.data) { - memset(mSurface.data, 0, mSize); - //if (bytesPerPixel(mSurface.format) == 4) { - // android_memset32((uint32_t*)mSurface.data, 0xFF0000FF, mSize); - //} else { - // android_memset16((uint16_t*)mSurface.data, 0xF800, mSize); - //} - } -} - -status_t LayerBitmap::getInfo(surface_info_t* info) const -{ - if (mSurface.data == 0) { - memset(info, 0, sizeof(surface_info_t)); - info->bits_offset = NO_MEMORY; - return NO_MEMORY; - } - info->w = uint16_t(width()); - info->h = uint16_t(height()); - info->stride= uint16_t(stride()); - info->bpr = uint16_t(stride() * bytesPerPixel(pixelFormat())); - info->format= uint8_t(pixelFormat()); - info->flags = surface_info_t::eBufferDirty; - info->bits_offset = ssize_t(mOffset); - return NO_ERROR; -} - -status_t LayerBitmap::resize(uint32_t w, uint32_t h) -{ - int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS); - return err; -} - -size_t LayerBitmap::size() const -{ - return mSize; -} - -void LayerBitmap::getBitmapSurface(copybit_image_t* img) const -{ - const sp<IMemoryHeap>& mh(getAllocator()->getMemoryHeap()); - void* sbase = mh->base(); - const GGLSurface& t(surface()); - img->w = t.stride ?: t.width; - img->h = t.vstride ?: t.height; - img->format = t.format; - img->offset = intptr_t(t.data) - intptr_t(sbase); - img->base = sbase; - img->fd = mh->heapID(); -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h deleted file mode 100644 index 9ad64c4..0000000 --- a/libs/surfaceflinger/LayerBitmap.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_BITMAP_H -#define ANDROID_LAYER_BITMAP_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Atomic.h> -#include <ui/PixelFormat.h> -#include <ui/Rect.h> -#include <private/ui/SharedState.h> -#include <pixelflinger/pixelflinger.h> - -class copybit_image_t; - -namespace android { - -// --------------------------------------------------------------------------- - -class IMemory; -class MemoryDealer; -class LayerBitmap; - -// --------------------------------------------------------------------------- - -class LayerBitmap -{ -public: - - enum { - // erase memory to ensure security when necessary - SECURE_BITS = 0x00000001 - }; - - LayerBitmap(); - ~LayerBitmap(); - status_t init(const sp<MemoryDealer>& allocator); - - status_t setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags = 0); - void clear(); - - status_t getInfo(surface_info_t* info) const; - status_t resize(uint32_t w, uint32_t h); - - const GGLSurface& surface() const { return mSurface; } - Rect bounds() const { return Rect(width(), height()); } - uint32_t width() const { return surface().width; } - uint32_t height() const { return surface().height; } - uint32_t stride() const { return surface().stride; } - PixelFormat pixelFormat() const { return surface().format; } - void* serverBits() const { return surface().data; } - size_t size() const; - const sp<MemoryDealer>& getAllocator() const { return mAllocator; } - void getBitmapSurface(copybit_image_t* img) const; - -private: - sp<MemoryDealer> mAllocator; - sp<IMemory> mBitsMemory; - uint32_t mAllocFlags; - ssize_t mOffset; - GGLSurface mSurface; - size_t mSize; - uint32_t mAlignment; -}; - -}; // namespace android - -#endif // ANDROID_LAYER_BITMAP_H diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp deleted file mode 100644 index d3e456f..0000000 --- a/libs/surfaceflinger/LayerBlur.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <GLES/gl.h> -#include <GLES/glext.h> - -#include "BlurFilter.h" -#include "LayerBlur.h" -#include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" - -namespace android { -// --------------------------------------------------------------------------- - -const uint32_t LayerBlur::typeInfo = LayerBaseClient::typeInfo | 8; -const char* const LayerBlur::typeID = "LayerBlur"; - -// --------------------------------------------------------------------------- - -LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display, - Client* client, int32_t i) - : LayerBaseClient(flinger, display, client, i), mCacheDirty(true), - mRefreshCache(true), mCacheAge(0), mTextureName(-1U) -{ -} - -LayerBlur::~LayerBlur() -{ - if (mTextureName != -1U) { - //glDeleteTextures(1, &mTextureName); - deletedTextures.add(mTextureName); - } -} - -void LayerBlur::setVisibleRegion(const Region& visibleRegion) -{ - LayerBaseClient::setVisibleRegion(visibleRegion); - if (visibleRegionScreen.isEmpty()) { - if (mTextureName != -1U) { - // We're not visible, free the texture up. - glBindTexture(GL_TEXTURE_2D, 0); - glDeleteTextures(1, &mTextureName); - mTextureName = -1U; - } - } -} - -uint32_t LayerBlur::doTransaction(uint32_t flags) -{ - // we're doing a transaction, refresh the cache! - if (!mFlinger->isFrozen()) { - mRefreshCache = true; - mCacheDirty = true; - flags |= eVisibleRegion; - this->contentDirty = true; - } - return LayerBase::doTransaction(flags); -} - -void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion) -{ - // this code-path must be as tight as possible, it's called each time - // the screen is composited. - if (UNLIKELY(!visibleRegionScreen.isEmpty())) { - // if anything visible below us is invalidated, the cache becomes dirty - if (!mCacheDirty && - !visibleRegionScreen.intersect(outDirtyRegion).isEmpty()) { - mCacheDirty = true; - } - if (mCacheDirty) { - if (!mFlinger->isFrozen()) { - // update everything below us that is visible - outDirtyRegion.orSelf(visibleRegionScreen); - nsecs_t now = systemTime(); - if ((now - mCacheAge) >= ms2ns(500)) { - mCacheAge = now; - mRefreshCache = true; - mCacheDirty = false; - } else { - if (!mAutoRefreshPending) { - mFlinger->signalDelayedEvent(ms2ns(500)); - mAutoRefreshPending = true; - } - } - } - } - } - LayerBase::unlockPageFlip(planeTransform, outDirtyRegion); -} - -void LayerBlur::onDraw(const Region& clip) const -{ - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const uint32_t fbHeight = hw.getHeight(); - int x = mTransformedBounds.left; - int y = mTransformedBounds.top; - int w = mTransformedBounds.width(); - int h = mTransformedBounds.height(); - GLint X = x; - GLint Y = fbHeight - (y + h); - if (X < 0) { - w += X; - X = 0; - } - if (Y < 0) { - h += Y; - Y = 0; - } - if (w<0 || h<0) { - // we're outside of the framebuffer - return; - } - - if (mTextureName == -1U) { - // create the texture name the first time - // can't do that in the ctor, because it runs in another thread. - glGenTextures(1, &mTextureName); - } - - Region::iterator iterator(clip); - if (iterator) { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, mTextureName); - - if (mRefreshCache) { - mRefreshCache = false; - mAutoRefreshPending = false; - - // allocate enough memory for 4-bytes (2 pixels) aligned data - const int32_t s = (w + 1) & ~1; - uint16_t* const pixels = (uint16_t*)malloc(s*h*2); - - // This reads the frame-buffer, so a h/w GL would have to - // finish() its rendering first. we don't want to do that - // too often. Read data is 4-bytes aligned. - glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); - - // blur that texture. - GGLSurface bl; - bl.version = sizeof(GGLSurface); - bl.width = w; - bl.height = h; - bl.stride = s; - bl.format = GGL_PIXEL_FORMAT_RGB_565; - bl.data = (GGLubyte*)pixels; - blurFilter(&bl, 8, 2); - - // NOTE: this works only because we have POT. we'd have to round the - // texture size up, otherwise. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); - - free((void*)pixels); - } - - const State& s = drawingState(); - if (UNLIKELY(s.alpha < 0xFF)) { - const GGLfixed alpha = (s.alpha << 16)/255; - glColor4x(0, 0, 0, alpha); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - } else { - glDisable(GL_BLEND); - } - - glDisable(GL_DITHER); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - if (UNLIKELY(transformed() - || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) { - // This is a very rare scenario. - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glScalef(1.0f/w, -1.0f/h, 1); - glTranslatef(-x, -y, 0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FIXED, 0, mVertices); - glTexCoordPointer(2, GL_FIXED, 0, mVertices); - Rect r; - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - } else { - Region::iterator iterator(clip); - if (iterator) { - // NOTE: this is marginally faster with the software gl, because - // glReadPixels() reads the fb bottom-to-top, however we'll - // skip all the jaccobian computations. - Rect r; - GLint crop[4] = { 0, 0, w, h }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - y = fbHeight - (y + h); - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, w, h); - } - } - } - } - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h deleted file mode 100644 index 24b1156..0000000 --- a/libs/surfaceflinger/LayerBlur.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_BLUR_H -#define ANDROID_LAYER_BLUR_H - -#include <stdint.h> -#include <sys/types.h> - -#include <private/ui/LayerState.h> - -#include <ui/Region.h> - -#include "LayerBase.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class LayerBlur : public LayerBaseClient -{ -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - LayerBlur(SurfaceFlinger* flinger, DisplayID display, - Client* client, int32_t i); - virtual ~LayerBlur(); - - virtual void onDraw(const Region& clip) const; - virtual bool needsBlending() const { return true; } - virtual bool isSecure() const { return false; } - - virtual uint32_t doTransaction(uint32_t flags); - virtual void setVisibleRegion(const Region& visibleRegion); - virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); - -private: - bool mCacheDirty; - mutable bool mRefreshCache; - mutable bool mAutoRefreshPending; - nsecs_t mCacheAge; - mutable GLuint mTextureName; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_BLUR_H diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp deleted file mode 100644 index 00fab70..0000000 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdint.h> -#include <math.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> -#include <utils/StopWatch.h> - -#include <utils/IPCThreadState.h> -#include <utils/IServiceManager.h> - -#include <ui/PixelFormat.h> -#include <ui/EGLDisplaySurface.h> - -#include "LayerBuffer.h" -#include "SurfaceFlinger.h" -#include "VRamHeap.h" -#include "DisplayHardware/DisplayHardware.h" - - -namespace android { - -// --------------------------------------------------------------------------- - -const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20; -const char* const LayerBuffer::typeID = "LayerBuffer"; - -// --------------------------------------------------------------------------- - -LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display, - Client* client, int32_t i) - : LayerBaseClient(flinger, display, client, i), - mNeedsBlending(false) -{ -} - -LayerBuffer::~LayerBuffer() -{ - sp<SurfaceBuffer> s(getClientSurface()); - if (s != 0) { - s->disown(); - mClientSurface.clear(); - } -} - -sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const -{ - Mutex::Autolock _l(mLock); - return mClientSurface.promote(); -} - -sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const -{ - sp<SurfaceBuffer> s; - Mutex::Autolock _l(mLock); - s = mClientSurface.promote(); - if (s == 0) { - s = new SurfaceBuffer(clientIndex(), - const_cast<LayerBuffer *>(this)); - mClientSurface = s; - } - return s; -} - -bool LayerBuffer::needsBlending() const { - return mNeedsBlending; -} - -void LayerBuffer::setNeedsBlending(bool blending) { - mNeedsBlending = blending; -} - -void LayerBuffer::postBuffer(ssize_t offset) -{ - sp<Source> source(getSource()); - if (source != 0) - source->postBuffer(offset); -} - -void LayerBuffer::unregisterBuffers() -{ - sp<Source> source(clearSource()); - if (source != 0) - source->unregisterBuffers(); -} - -uint32_t LayerBuffer::doTransaction(uint32_t flags) -{ - sp<Source> source(getSource()); - if (source != 0) - source->onTransaction(flags); - return LayerBase::doTransaction(flags); -} - -void LayerBuffer::unlockPageFlip(const Transform& planeTransform, - Region& outDirtyRegion) -{ - // this code-path must be as tight as possible, it's called each time - // the screen is composited. - sp<Source> source(getSource()); - if (source != 0) - source->onVisibilityResolved(planeTransform); - LayerBase::unlockPageFlip(planeTransform, outDirtyRegion); -} - -void LayerBuffer::onDraw(const Region& clip) const -{ - sp<Source> source(getSource()); - if (LIKELY(source != 0)) { - source->onDraw(clip); - } else { - clearWithOpenGL(clip); - } -} - -bool LayerBuffer::transformed() const -{ - sp<Source> source(getSource()); - if (LIKELY(source != 0)) - return source->transformed(); - return false; -} - -/** - * This creates a "buffer" source for this surface - */ -status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers) -{ - Mutex::Autolock _l(mLock); - if (mSource != 0) - return INVALID_OPERATION; - - sp<BufferSource> source = new BufferSource(*this, buffers); - - status_t result = source->getStatus(); - if (result == NO_ERROR) { - mSource = source; - } - return result; -} - -/** - * This creates an "overlay" source for this surface - */ -sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f) -{ - sp<OverlayRef> result; - Mutex::Autolock _l(mLock); - if (mSource != 0) - return result; - - sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f); - if (result != 0) { - mSource = source; - } - return result; -} - -sp<LayerBuffer::Source> LayerBuffer::getSource() const { - Mutex::Autolock _l(mLock); - return mSource; -} - -sp<LayerBuffer::Source> LayerBuffer::clearSource() { - sp<Source> source; - Mutex::Autolock _l(mLock); - source = mSource; - mSource.clear(); - return source; -} - -// ============================================================================ -// LayerBuffer::SurfaceBuffer -// ============================================================================ - -LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner) -: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner) -{ -} - -LayerBuffer::SurfaceBuffer::~SurfaceBuffer() -{ - unregisterBuffers(); - mOwner = 0; -} - -status_t LayerBuffer::SurfaceBuffer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch (code) { - case REGISTER_BUFFERS: - case UNREGISTER_BUFFERS: - case CREATE_OVERLAY: - { - // codes that require permission check - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int self_pid = getpid(); - if (LIKELY(pid != self_pid)) { - // we're called from a different process, do the real check - if (!checkCallingPermission( - String16("android.permission.ACCESS_SURFACE_FLINGER"))) - { - const int uid = ipc->getCallingUid(); - LOGE("Permission Denial: " - "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); - return PERMISSION_DENIED; - } - } - } - } - return LayerBaseClient::Surface::onTransact(code, data, reply, flags); -} - -status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers) -{ - LayerBuffer* owner(getOwner()); - if (owner) - return owner->registerBuffers(buffers); - return NO_INIT; -} - -void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset) -{ - LayerBuffer* owner(getOwner()); - if (owner) - owner->postBuffer(offset); -} - -void LayerBuffer::SurfaceBuffer::unregisterBuffers() -{ - LayerBuffer* owner(getOwner()); - if (owner) - owner->unregisterBuffers(); -} - -sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay( - uint32_t w, uint32_t h, int32_t format) { - sp<OverlayRef> result; - LayerBuffer* owner(getOwner()); - if (owner) - result = owner->createOverlay(w, h, format); - return result; -} - -void LayerBuffer::SurfaceBuffer::disown() -{ - Mutex::Autolock _l(mLock); - mOwner = 0; -} - -// ============================================================================ -// LayerBuffer::Buffer -// ============================================================================ - -LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset) - : mBufferHeap(buffers) -{ - NativeBuffer& src(mNativeBuffer); - 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.offset = offset; - src.img.base = buffers.heap->base(); - src.img.fd = buffers.heap->heapID(); -} - -LayerBuffer::Buffer::~Buffer() -{ -} - -// ============================================================================ -// LayerBuffer::Source -// LayerBuffer::BufferSource -// LayerBuffer::OverlaySource -// ============================================================================ - -LayerBuffer::Source::Source(LayerBuffer& layer) - : mLayer(layer) -{ -} -LayerBuffer::Source::~Source() { -} -void LayerBuffer::Source::onDraw(const Region& clip) const { -} -void LayerBuffer::Source::onTransaction(uint32_t flags) { -} -void LayerBuffer::Source::onVisibilityResolved( - const Transform& planeTransform) { -} -void LayerBuffer::Source::postBuffer(ssize_t offset) { -} -void LayerBuffer::Source::unregisterBuffers() { -} -bool LayerBuffer::Source::transformed() const { - return mLayer.mTransformed; -} - -// --------------------------------------------------------------------------- - -LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer, - const ISurface::BufferHeap& buffers) - : Source(layer), mStatus(NO_ERROR), - mBufferSize(0), mTextureName(-1U) -{ - if (buffers.heap == NULL) { - // this is allowed, but in this case, it is illegal to receive - // postBuffer(). The surface just erases the framebuffer with - // fully transparent pixels. - mBufferHeap = buffers; - mLayer.setNeedsBlending(false); - return; - } - - status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT; - if (err != NO_ERROR) { - LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err)); - mStatus = err; - return; - } - - PixelFormatInfo info; - err = getPixelFormatInfo(buffers.format, &info); - if (err != NO_ERROR) { - LOGE("LayerBuffer::BufferSource: invalid format %d (%s)", - buffers.format, strerror(err)); - mStatus = err; - return; - } - - if (buffers.hor_stride<0 || buffers.ver_stride<0) { - LOGE("LayerBuffer::BufferSource: invalid parameters " - "(w=%d, h=%d, xs=%d, ys=%d)", - buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride); - mStatus = BAD_VALUE; - return; - } - - mBufferHeap = buffers; - mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0); - mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride; - mLayer.forceVisibilityTransaction(); - -} - -LayerBuffer::BufferSource::~BufferSource() -{ - if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); - } -} - -void LayerBuffer::BufferSource::postBuffer(ssize_t offset) -{ - ISurface::BufferHeap buffers; - { // scope for the lock - Mutex::Autolock _l(mLock); - buffers = mBufferHeap; - if (buffers.heap != 0) { - const size_t memorySize = buffers.heap->getSize(); - if ((size_t(offset) + mBufferSize) > memorySize) { - LOGE("LayerBuffer::BufferSource::postBuffer() " - "invalid buffer (offset=%d, size=%d, heap-size=%d", - int(offset), int(mBufferSize), int(memorySize)); - return; - } - } - } - - sp<Buffer> buffer; - if (buffers.heap != 0) { - buffer = new LayerBuffer::Buffer(buffers, offset); - if (buffer->getStatus() != NO_ERROR) - buffer.clear(); - setBuffer(buffer); - mLayer.invalidate(); - } -} - -void LayerBuffer::BufferSource::unregisterBuffers() -{ - Mutex::Autolock _l(mLock); - mBufferHeap.heap.clear(); - mBuffer.clear(); - mLayer.invalidate(); -} - -sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const -{ - Mutex::Autolock _l(mLock); - return mBuffer; -} - -void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer) -{ - Mutex::Autolock _l(mLock); - mBuffer = buffer; -} - -bool LayerBuffer::BufferSource::transformed() const -{ - return mBufferHeap.transform ? true : Source::transformed(); -} - -void LayerBuffer::BufferSource::onDraw(const Region& clip) const -{ - sp<Buffer> buffer(getBuffer()); - if (UNLIKELY(buffer == 0)) { - // nothing to do, we don't have a buffer - mLayer.clearWithOpenGL(clip); - return; - } - - status_t err = NO_ERROR; - NativeBuffer src(buffer->getBuffer()); - const Rect& transformedBounds = mLayer.getTransformedBounds(); - const int can_use_copybit = mLayer.canUseCopybit(); - - if (can_use_copybit) { - const int src_width = src.crop.r - src.crop.l; - const int src_height = src.crop.b - src.crop.t; - int W = transformedBounds.width(); - int H = transformedBounds.height(); - if (mLayer.getOrientation() & Transform::ROT_90) { - int t(W); W=H; H=t; - } - - /* With LayerBuffer, it is likely that we'll have to rescale the - * surface, because this is often used for video playback or - * camera-preview. Since we want these operation as fast as possible - * we make sure we can use the 2D H/W even if it doesn't support - * the requested scale factor, in which case we perform the scaling - * in several passes. */ - - copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine(); - const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT); - const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT); - - float xscale = 1.0f; - if (src_width > W*min) xscale = 1.0f / min; - else if (src_width*mag < W) xscale = mag; - - float yscale = 1.0f; - if (src_height > H*min) yscale = 1.0f / min; - else if (src_height*mag < H) yscale = mag; - - if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) { - if (UNLIKELY(mTemporaryDealer == 0)) { - // allocate a memory-dealer for this the first time - mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); - mTempBitmap.init(mTemporaryDealer); - } - - const int tmp_w = floorf(src_width * xscale); - const int tmp_h = floorf(src_height * yscale); - err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format); - - if (LIKELY(err == NO_ERROR)) { - NativeBuffer tmp; - mTempBitmap.getBitmapSurface(&tmp.img); - tmp.crop.l = 0; - tmp.crop.t = 0; - tmp.crop.r = tmp.img.w; - tmp.crop.b = tmp.img.h; - - region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b))); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - err = copybit->stretch(copybit, - &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it); - src = tmp; - } - } - - const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware()); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(transformedBounds); - const State& s(mLayer.drawingState()); - region_iterator it(clip); - - // pick the right orientation for this buffer - int orientation = mLayer.getOrientation(); - if (UNLIKELY(mBufferHeap.transform)) { - Transform rot90; - GraphicPlane::orientationToTransfrom( - ISurfaceComposer::eOrientation90, 0, 0, &rot90); - const Transform& planeTransform(mLayer.graphicPlane(0).transform()); - const Layer::State& s(mLayer.drawingState()); - Transform tr(planeTransform * s.transform * rot90); - orientation = tr.getOrientation(); - } - - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - - err = copybit->stretch(copybit, - &dst, &src.img, &drect, &src.crop, &it); - if (err != NO_ERROR) { - LOGE("copybit failed (%s)", strerror(err)); - } - } - - if (!can_use_copybit || err) { - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = mLayer.createTexture(); - } - GLuint w = 0; - GLuint h = 0; - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.crop.r; - t.height = src.crop.b; - t.stride = src.img.w; - t.vstride= src.img.h; - t.format = src.img.format; - t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); - const Region dirty(Rect(t.width, t.height)); - mLayer.loadTexture(dirty, mTextureName, t, w, h); - mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform); - } -} - - -// --------------------------------------------------------------------------- - -LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer, - sp<OverlayRef>* overlayRef, - uint32_t w, uint32_t h, int32_t format) - : Source(layer), mVisibilityChanged(false), - mOverlay(0), mOverlayHandle(0), mOverlayDevice(0) -{ - overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine(); - if (overlay_dev == NULL) { - // overlays not supported - return; - } - - mOverlayDevice = overlay_dev; - overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format); - if (overlay == NULL) { - // couldn't create the overlay (no memory? no more overlays?) - return; - } - - // enable dithering... - overlay_dev->setParameter(overlay_dev, overlay, - OVERLAY_DITHER, OVERLAY_ENABLE); - - mOverlay = overlay; - mWidth = overlay->w; - mHeight = overlay->h; - mFormat = overlay->format; - mWidthStride = overlay->w_stride; - mHeightStride = overlay->h_stride; - - mOverlayHandle = overlay->getHandleRef(overlay); - - // NOTE: here it's okay to acquire a reference to "this"m as long as - // the reference is not released before we leave the ctor. - sp<OverlayChannel> channel = new OverlayChannel(this); - - *overlayRef = new OverlayRef(mOverlayHandle, channel, - mWidth, mHeight, mFormat, mWidthStride, mHeightStride); -} - -LayerBuffer::OverlaySource::~OverlaySource() -{ - if (mOverlay && mOverlayDevice) { - overlay_control_device_t* overlay_dev = mOverlayDevice; - overlay_dev->destroyOverlay(overlay_dev, mOverlay); - } -} - -void LayerBuffer::OverlaySource::onTransaction(uint32_t flags) -{ - const Layer::State& front(mLayer.drawingState()); - const Layer::State& temp(mLayer.currentState()); - if (temp.sequence != front.sequence) { - mVisibilityChanged = true; - } -} - -void LayerBuffer::OverlaySource::onVisibilityResolved( - const Transform& planeTransform) -{ - // this code-path must be as tight as possible, it's called each time - // the screen is composited. - if (UNLIKELY(mOverlay != 0)) { - if (mVisibilityChanged) { - mVisibilityChanged = false; - const Rect& bounds = mLayer.getTransformedBounds(); - int x = bounds.left; - int y = bounds.top; - int w = bounds.width(); - int h = bounds.height(); - - // we need a lock here to protect "destroy" - Mutex::Autolock _l(mLock); - if (mOverlay) { - overlay_control_device_t* overlay_dev = mOverlayDevice; - overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h); - overlay_dev->setParameter(overlay_dev, mOverlay, - OVERLAY_TRANSFORM, mLayer.getOrientation()); - } - } - } -} - -void LayerBuffer::OverlaySource::serverDestroy() -{ - mLayer.clearSource(); - destroyOverlay(); -} - -void LayerBuffer::OverlaySource::destroyOverlay() -{ - // we need a lock here to protect "onVisibilityResolved" - Mutex::Autolock _l(mLock); - if (mOverlay) { - overlay_control_device_t* overlay_dev = mOverlayDevice; - overlay_dev->destroyOverlay(overlay_dev, mOverlay); - mOverlay = 0; - } -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h deleted file mode 100644 index 2dc77f1..0000000 --- a/libs/surfaceflinger/LayerBuffer.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_BUFFER_H -#define ANDROID_LAYER_BUFFER_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/IMemory.h> -#include <private/ui/LayerState.h> -#include <EGL/eglnatives.h> - -#include "LayerBase.h" -#include "LayerBitmap.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class MemoryDealer; -class Region; -class OverlayRef; - -class LayerBuffer : public LayerBaseClient -{ - class Source : public LightRefBase<Source> { - public: - Source(LayerBuffer& layer); - virtual ~Source(); - virtual void onDraw(const Region& clip) const; - virtual void onTransaction(uint32_t flags); - virtual void onVisibilityResolved(const Transform& planeTransform); - virtual void postBuffer(ssize_t offset); - virtual void unregisterBuffers(); - virtual bool transformed() const; - protected: - LayerBuffer& mLayer; - }; - - -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - LayerBuffer(SurfaceFlinger* flinger, DisplayID display, - Client* client, int32_t i); - virtual ~LayerBuffer(); - - virtual bool needsBlending() const; - - virtual sp<LayerBaseClient::Surface> getSurface() const; - virtual void onDraw(const Region& clip) const; - virtual uint32_t doTransaction(uint32_t flags); - virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); - virtual bool transformed() const; - - status_t registerBuffers(const ISurface::BufferHeap& buffers); - void postBuffer(ssize_t offset); - void unregisterBuffers(); - sp<OverlayRef> createOverlay(uint32_t w, uint32_t h, int32_t format); - - sp<Source> getSource() const; - sp<Source> clearSource(); - void setNeedsBlending(bool blending); - const Rect& getTransformedBounds() const { - return mTransformedBounds; - } - -private: - struct NativeBuffer { - copybit_image_t img; - copybit_rect_t crop; - }; - - class Buffer : public LightRefBase<Buffer> { - public: - Buffer(const ISurface::BufferHeap& buffers, ssize_t offset); - inline status_t getStatus() const { - return mBufferHeap.heap!=0 ? NO_ERROR : NO_INIT; - } - inline const NativeBuffer& getBuffer() const { - return mNativeBuffer; - } - protected: - friend class LightRefBase<Buffer>; - Buffer& operator = (const Buffer& rhs); - Buffer(const Buffer& rhs); - ~Buffer(); - private: - ISurface::BufferHeap mBufferHeap; - NativeBuffer mNativeBuffer; - }; - - class BufferSource : public Source { - public: - BufferSource(LayerBuffer& layer, const ISurface::BufferHeap& buffers); - virtual ~BufferSource(); - - status_t getStatus() const { return mStatus; } - sp<Buffer> getBuffer() const; - void setBuffer(const sp<Buffer>& buffer); - - virtual void onDraw(const Region& clip) const; - virtual void postBuffer(ssize_t offset); - virtual void unregisterBuffers(); - virtual bool transformed() const; - private: - mutable Mutex mLock; - sp<Buffer> mBuffer; - status_t mStatus; - ISurface::BufferHeap mBufferHeap; - size_t mBufferSize; - mutable sp<MemoryDealer> mTemporaryDealer; - mutable LayerBitmap mTempBitmap; - mutable GLuint mTextureName; - }; - - class OverlaySource : public Source { - public: - OverlaySource(LayerBuffer& layer, - sp<OverlayRef>* overlayRef, - uint32_t w, uint32_t h, int32_t format); - virtual ~OverlaySource(); - virtual void onTransaction(uint32_t flags); - virtual void onVisibilityResolved(const Transform& planeTransform); - private: - void serverDestroy(); - void destroyOverlay(); - class OverlayChannel : public BnOverlay { - mutable Mutex mLock; - sp<OverlaySource> mSource; - virtual void destroy() { - sp<OverlaySource> source; - { // scope for the lock; - Mutex::Autolock _l(mLock); - source = mSource; - mSource.clear(); - } - if (source != 0) { - source->serverDestroy(); - } - } - public: - OverlayChannel(const sp<OverlaySource>& source) - : mSource(source) { - } - }; - friend class OverlayChannel; - bool mVisibilityChanged; - - overlay_t* mOverlay; - overlay_handle_t mOverlayHandle; - overlay_control_device_t* mOverlayDevice; - uint32_t mWidth; - uint32_t mHeight; - int32_t mFormat; - int32_t mWidthStride; - int32_t mHeightStride; - mutable Mutex mLock; - }; - - - class SurfaceBuffer : public LayerBaseClient::Surface - { - public: - SurfaceBuffer(SurfaceID id, LayerBuffer* owner); - virtual ~SurfaceBuffer(); - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); - virtual void postBuffer(ssize_t offset); - virtual void unregisterBuffers(); - virtual sp<OverlayRef> createOverlay( - uint32_t w, uint32_t h, int32_t format); - void disown(); - private: - LayerBuffer* getOwner() const { - Mutex::Autolock _l(mLock); - return mOwner; - } - mutable Mutex mLock; - LayerBuffer* mOwner; - }; - - friend class SurfaceFlinger; - sp<SurfaceBuffer> getClientSurface() const; - - mutable Mutex mLock; - sp<Source> mSource; - - bool mInvalidate; - bool mNeedsBlending; - mutable wp<SurfaceBuffer> mClientSurface; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_BUFFER_H diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp deleted file mode 100644 index 0c347cc..0000000 --- a/libs/surfaceflinger/LayerDim.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include "LayerDim.h" -#include "SurfaceFlinger.h" -#include "VRamHeap.h" -#include "DisplayHardware/DisplayHardware.h" - -namespace android { -// --------------------------------------------------------------------------- - -const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10; -const char* const LayerDim::typeID = "LayerDim"; -sp<MemoryDealer> LayerDim::mDimmerDealer; -LayerBitmap LayerDim::mDimmerBitmap; - -// --------------------------------------------------------------------------- - -LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display, - Client* client, int32_t i) - : LayerBaseClient(flinger, display, client, i) -{ -} - -void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) -{ - // must only be called once. - mDimmerDealer = flinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); - if (mDimmerDealer != 0) { - mDimmerBitmap.init(mDimmerDealer); - mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565); - mDimmerBitmap.clear(); - } -} - -LayerDim::~LayerDim() -{ -} - -void LayerDim::onDraw(const Region& clip) const -{ - const State& s(drawingState()); - - Region::iterator iterator(clip); - if (s.alpha>0 && iterator) { - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - - status_t err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - // StopWatch watch("copybit"); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - - copybit_image_t src; - mDimmerBitmap.getBitmapSurface(&src); - const copybit_rect_t& srect(drect); - - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - region_iterator it(clip); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!can_use_copybit || err) { - const GGLfixed alpha = (s.alpha << 16)/255; - const uint32_t fbHeight = hw.getHeight(); - glDisable(GL_TEXTURE_2D); - glDisable(GL_DITHER); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4x(0, 0, 0, alpha); - glVertexPointer(2, GL_FIXED, 0, mVertices); - Rect r; - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - } - } -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h deleted file mode 100644 index 3e37a47..0000000 --- a/libs/surfaceflinger/LayerDim.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_DIM_H -#define ANDROID_LAYER_DIM_H - -#include <stdint.h> -#include <sys/types.h> - -#include "LayerBase.h" -#include "LayerBitmap.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class LayerDim : public LayerBaseClient -{ -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - LayerDim(SurfaceFlinger* flinger, DisplayID display, - Client* client, int32_t i); - virtual ~LayerDim(); - - virtual void onDraw(const Region& clip) const; - virtual bool needsBlending() const { return true; } - virtual bool isSecure() const { return false; } - - static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h); - -private: - static sp<MemoryDealer> mDimmerDealer; - static LayerBitmap mDimmerBitmap; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_DIM_H diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp deleted file mode 100644 index 2b72d7c..0000000 --- a/libs/surfaceflinger/LayerOrientationAnim.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <core/SkBitmap.h> - -#include <ui/EGLDisplaySurface.h> - -#include "LayerBase.h" -#include "LayerOrientationAnim.h" -#include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" -#include "OrientationAnimation.h" - -namespace android { -// --------------------------------------------------------------------------- - -const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80; -const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim"; - -// --------------------------------------------------------------------------- - -LayerOrientationAnim::LayerOrientationAnim( - SurfaceFlinger* flinger, DisplayID display, - OrientationAnimation* anim, - const LayerBitmap& bitmap, - const LayerBitmap& bitmapIn) - : LayerBase(flinger, display), mAnim(anim), - mBitmap(bitmap), mBitmapIn(bitmapIn), - mTextureName(-1), mTextureNameIn(-1) -{ - mStartTime = systemTime(); - mFinishTime = 0; - mOrientationCompleted = false; - mFirstRedraw = false; - mLastNormalizedTime = 0; - mLastScale = 0; - mNeedsBlending = false; -} - -LayerOrientationAnim::~LayerOrientationAnim() -{ - if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); - } - if (mTextureNameIn != -1U) { - LayerBase::deletedTextures.add(mTextureNameIn); - } -} - -bool LayerOrientationAnim::needsBlending() const -{ - return mNeedsBlending; -} - -Point LayerOrientationAnim::getPhysicalSize() const -{ - const GraphicPlane& plane(graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - return Point(hw.getWidth(), hw.getHeight()); -} - -void LayerOrientationAnim::validateVisibility(const Transform&) -{ - const Layer::State& s(drawingState()); - const Transform tr(s.transform); - const Point size(getPhysicalSize()); - uint32_t w = size.x; - uint32_t h = size.y; - mTransformedBounds = tr.makeBounds(w, h); - mLeft = tr.tx(); - mTop = tr.ty(); - transparentRegionScreen.clear(); - mTransformed = true; - mCanUseCopyBit = false; - copybit_device_t* copybit = mFlinger->getBlitEngine(); - if (copybit) { - mCanUseCopyBit = true; - } -} - -void LayerOrientationAnim::onOrientationCompleted() -{ - mFinishTime = systemTime(); - mOrientationCompleted = true; - mFirstRedraw = true; - mNeedsBlending = true; - mFlinger->invalidateLayerVisibility(this); -} - -void LayerOrientationAnim::onDraw(const Region& clip) const -{ - // Animation... - const float MIN_SCALE = 0.5f; - const float DURATION = ms2ns(200); - const float BOUNCES_PER_SECOND = 1.618f; - const float BOUNCES_AMPLITUDE = 1.0f/32.0f; - - const nsecs_t now = systemTime(); - float scale, alpha; - - if (mOrientationCompleted) { - if (mFirstRedraw) { - mFirstRedraw = false; - - // make a copy of what's on screen - copybit_image_t image; - mBitmapIn.getBitmapSurface(&image); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - hw.copyBackToImage(image); - - // and erase the screen for this round - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - - // FIXME: code below is gross - mNeedsBlending = false; - LayerOrientationAnim* self(const_cast<LayerOrientationAnim*>(this)); - mFlinger->invalidateLayerVisibility(self); - } - - // make sure pick-up where we left off - const float duration = DURATION * mLastNormalizedTime; - const float normalizedTime = (float(now - mFinishTime) / duration); - if (normalizedTime <= 1.0f) { - const float squaredTime = normalizedTime*normalizedTime; - scale = (1.0f - mLastScale)*squaredTime + mLastScale; - alpha = (1.0f - normalizedTime); - alpha *= alpha; - alpha *= alpha; - } else { - mAnim->onAnimationFinished(); - scale = 1.0f; - alpha = 0.0f; - } - } else { - const float normalizedTime = float(now - mStartTime) / DURATION; - if (normalizedTime <= 1.0f) { - mLastNormalizedTime = normalizedTime; - const float squaredTime = normalizedTime*normalizedTime; - scale = (MIN_SCALE-1.0f)*squaredTime + 1.0f; - alpha = 1.0f; - } else { - mLastNormalizedTime = 1.0f; - const float to_seconds = DURATION / seconds(1); - const float phi = BOUNCES_PER_SECOND * - (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); - scale = MIN_SCALE + BOUNCES_AMPLITUDE * (1.0f - cosf(phi)); - alpha = 1.0f; - } - mLastScale = scale; - } - drawScaled(scale, alpha); -} - -void LayerOrientationAnim::drawScaled(float f, float alpha) const -{ - copybit_image_t dst; - const GraphicPlane& plane(graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - hw.getDisplaySurface(&dst); - - // clear screen - // TODO: with update on demand, we may be able - // to not erase the screen at all during the animation - if (!mOrientationCompleted) { - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - } - - const int w = dst.w*f; - const int h = dst.h*f; - const int xc = uint32_t(dst.w-w)/2; - const int yc = uint32_t(dst.h-h)/2; - const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; - - copybit_image_t src; - mBitmap.getBitmapSurface(&src); - const copybit_rect_t srect = { 0, 0, src.w, src.h }; - - int err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - - if (alpha < 1.0f) { - copybit_image_t srcIn; - mBitmapIn.getBitmapSurface(&srcIn); - region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b ))); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - err = copybit->stretch(copybit, &dst, &srcIn, &drect, &srect, &it); - } - - if (!err && alpha > 0.0f) { - region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b ))); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alpha*255)); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err)); - } - if (!can_use_copybit || err) { - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.w; - t.height = src.h; - t.stride = src.w; - t.vstride= src.h; - t.format = src.format; - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - - Transform tr; - tr.set(f,0,0,f); - tr.set(xc, yc); - - // FIXME: we should not access mVertices and mDrawingState like that, - // but since we control the animation, we know it's going to work okay. - // eventually we'd need a more formal way of doing things like this. - LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this)); - tr.transform(self.mVertices[0], 0, 0); - tr.transform(self.mVertices[1], 0, src.h); - tr.transform(self.mVertices[2], src.w, src.h); - tr.transform(self.mVertices[3], src.w, 0); - if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { - // Too slow to do this in software - self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; - } - - if (alpha < 1.0f) { - copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (UNLIKELY(mTextureNameIn == -1LU)) { - mTextureNameIn = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureNameIn, t, w, h); - } - self.mDrawingState.alpha = 255; - const Region clip(Rect( drect.l, drect.t, drect.r, drect.b )); - drawWithOpenGL(clip, mTextureName, t); - } - - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); - } - self.mDrawingState.alpha = int(alpha*255); - const Region clip(Rect( drect.l, drect.t, drect.r, drect.b )); - drawWithOpenGL(clip, mTextureName, t); - } -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h deleted file mode 100644 index 73676859..0000000 --- a/libs/surfaceflinger/LayerOrientationAnim.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_ORIENTATION_ANIM_H -#define ANDROID_LAYER_ORIENTATION_ANIM_H - -#include <stdint.h> -#include <sys/types.h> -#include <utils/threads.h> -#include <utils/Parcel.h> - -#include "LayerBase.h" -#include "LayerBitmap.h" - -namespace android { - -// --------------------------------------------------------------------------- -class OrientationAnimation; - -class LayerOrientationAnim : public LayerBase -{ -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, - OrientationAnimation* anim, - const LayerBitmap& zoomOut, - const LayerBitmap& zoomIn); - virtual ~LayerOrientationAnim(); - - void onOrientationCompleted(); - - virtual void onDraw(const Region& clip) const; - virtual Point getPhysicalSize() const; - virtual void validateVisibility(const Transform& globalTransform); - virtual bool needsBlending() const; - virtual bool isSecure() const { return false; } -private: - void drawScaled(float scale, float alpha) const; - - OrientationAnimation* mAnim; - LayerBitmap mBitmap; - LayerBitmap mBitmapIn; - nsecs_t mStartTime; - nsecs_t mFinishTime; - bool mOrientationCompleted; - mutable bool mFirstRedraw; - mutable float mLastNormalizedTime; - mutable float mLastScale; - mutable GLuint mTextureName; - mutable GLuint mTextureNameIn; - mutable bool mNeedsBlending; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_ORIENTATION_ANIM_H diff --git a/libs/surfaceflinger/MODULE_LICENSE_APACHE2 b/libs/surfaceflinger/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/libs/surfaceflinger/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp deleted file mode 100644 index f6f1326..0000000 --- a/libs/surfaceflinger/OrientationAnimation.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdint.h> -#include <sys/types.h> -#include <limits.h> - -#include "LayerOrientationAnim.h" -#include "OrientationAnimation.h" -#include "SurfaceFlinger.h" -#include "VRamHeap.h" - -#include "DisplayHardware/DisplayHardware.h" - -namespace android { - -// --------------------------------------------------------------------------- - -OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger) - : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE) -{ - // allocate a memory-dealer for this the first time - mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap( - ISurfaceComposer::eHardware); -} - -OrientationAnimation::~OrientationAnimation() -{ -} - -void OrientationAnimation::onOrientationChanged() -{ - if (mState == DONE) - mState = PREPARE; -} - -void OrientationAnimation::onAnimationFinished() -{ - if (mState != DONE) - mState = FINISH; -} - -bool OrientationAnimation::run_impl() -{ - bool skip_frame; - switch (mState) { - default: - case DONE: - skip_frame = done(); - break; - case PREPARE: - skip_frame = prepare(); - break; - case PHASE1: - skip_frame = phase1(); - break; - case PHASE2: - skip_frame = phase2(); - break; - case FINISH: - skip_frame = finished(); - break; - } - return skip_frame; -} - -bool OrientationAnimation::done() -{ - if (mFlinger->isFrozen()) { - // we are not allowed to draw, but pause a bit to make sure - // apps don't end up using the whole CPU, if they depend on - // surfaceflinger for synchronization. - usleep(8333); // 8.3ms ~ 120fps - return true; - } - return false; -} - -bool OrientationAnimation::prepare() -{ - mState = PHASE1; - - const GraphicPlane& plane(mFlinger->graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - const uint32_t w = hw.getWidth(); - const uint32_t h = hw.getHeight(); - - LayerBitmap bitmap; - bitmap.init(mTemporaryDealer); - bitmap.setBits(w, h, 1, hw.getFormat()); - - LayerBitmap bitmapIn; - bitmapIn.init(mTemporaryDealer); - bitmapIn.setBits(w, h, 1, hw.getFormat()); - - copybit_image_t front; - bitmap.getBitmapSurface(&front); - hw.copyFrontToImage(front); - - LayerOrientationAnim* l = new LayerOrientationAnim( - mFlinger.get(), 0, this, bitmap, bitmapIn); - l->initStates(w, h, 0); - l->setLayer(INT_MAX-1); - mFlinger->addLayer(l); - mLayerOrientationAnim = l; - return true; -} - -bool OrientationAnimation::phase1() -{ - if (mFlinger->isFrozen() == false) { - // start phase 2 - mState = PHASE2; - mLayerOrientationAnim->onOrientationCompleted(); - mLayerOrientationAnim->invalidate(); - return true; - - } - mLayerOrientationAnim->invalidate(); - return false; -} - -bool OrientationAnimation::phase2() -{ - // do the 2nd phase of the animation - mLayerOrientationAnim->invalidate(); - return false; -} - -bool OrientationAnimation::finished() -{ - mState = DONE; - mFlinger->removeLayer(mLayerOrientationAnim); - mLayerOrientationAnim = NULL; - return true; -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h deleted file mode 100644 index ba33fce..0000000 --- a/libs/surfaceflinger/OrientationAnimation.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_ORIENTATION_ANIMATION_H -#define ANDROID_ORIENTATION_ANIMATION_H - -#include <stdint.h> -#include <sys/types.h> - -#include "SurfaceFlinger.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class SurfaceFlinger; -class MemoryDealer; -class LayerOrientationAnim; - -class OrientationAnimation -{ -public: - OrientationAnimation(const sp<SurfaceFlinger>& flinger); - virtual ~OrientationAnimation(); - - void onOrientationChanged(); - void onAnimationFinished(); - inline bool run() { - if (LIKELY(mState == DONE)) - return false; - return run_impl(); - } - -private: - enum { - DONE = 0, - PREPARE, - PHASE1, - PHASE2, - FINISH - }; - - bool run_impl(); - bool done(); - bool prepare(); - bool phase1(); - bool phase2(); - bool finished(); - - sp<SurfaceFlinger> mFlinger; - sp<MemoryDealer> mTemporaryDealer; - LayerOrientationAnim* mLayerOrientationAnim; - int mState; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_ORIENTATION_ANIMATION_H diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp deleted file mode 100644 index 900282a..0000000 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ /dev/null @@ -1,1840 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <math.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <cutils/log.h> -#include <cutils/properties.h> - -#include <utils/IPCThreadState.h> -#include <utils/IServiceManager.h> -#include <utils/MemoryDealer.h> -#include <utils/MemoryBase.h> -#include <utils/String8.h> -#include <utils/String16.h> -#include <utils/StopWatch.h> - -#include <ui/PixelFormat.h> -#include <ui/DisplayInfo.h> -#include <ui/EGLDisplaySurface.h> - -#include <pixelflinger/pixelflinger.h> -#include <GLES/gl.h> - -#include "clz.h" -#include "CPUGauge.h" -#include "Layer.h" -#include "LayerBlur.h" -#include "LayerBuffer.h" -#include "LayerDim.h" -#include "LayerBitmap.h" -#include "LayerOrientationAnim.h" -#include "OrientationAnimation.h" -#include "SurfaceFlinger.h" -#include "VRamHeap.h" - -#include "DisplayHardware/DisplayHardware.h" -#include "GPUHardware/GPUHardware.h" - - -#define DISPLAY_COUNT 1 - -namespace android { - -// --------------------------------------------------------------------------- - -void SurfaceFlinger::instantiate() { - defaultServiceManager()->addService( - String16("SurfaceFlinger"), new SurfaceFlinger()); -} - -void SurfaceFlinger::shutdown() { - // we should unregister here, but not really because - // when (if) the service manager goes away, all the services - // it has a reference to will leave too. -} - -// --------------------------------------------------------------------------- - -SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs) - : lookup(rhs.lookup), layers(rhs.layers) -{ -} - -ssize_t SurfaceFlinger::LayerVector::indexOf( - LayerBase* key, size_t guess) const -{ - if (guess<size() && lookup.keyAt(guess) == key) - return guess; - const ssize_t i = lookup.indexOfKey(key); - if (i>=0) { - const size_t idx = lookup.valueAt(i); - LOG_ASSERT(layers[idx]==key, - "LayerVector[%p]: layers[%d]=%p, key=%p", - this, int(idx), layers[idx], key); - return idx; - } - return i; -} - -ssize_t SurfaceFlinger::LayerVector::add( - LayerBase* layer, - Vector<LayerBase*>::compar_t cmp) -{ - size_t count = layers.size(); - ssize_t l = 0; - ssize_t h = count-1; - ssize_t mid; - LayerBase* const* a = layers.array(); - while (l <= h) { - mid = l + (h - l)/2; - const int c = cmp(a+mid, &layer); - if (c == 0) { l = mid; break; } - else if (c<0) { l = mid+1; } - else { h = mid-1; } - } - size_t order = l; - while (order<count && !cmp(&layer, a+order)) { - order++; - } - count = lookup.size(); - for (size_t i=0 ; i<count ; i++) { - if (lookup.valueAt(i) >= order) { - lookup.editValueAt(i)++; - } - } - layers.insertAt(layer, order); - lookup.add(layer, order); - return order; -} - -ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer) -{ - const ssize_t keyIndex = lookup.indexOfKey(layer); - if (keyIndex >= 0) { - const size_t index = lookup.valueAt(keyIndex); - LOG_ASSERT(layers[index]==layer, - "LayerVector[%p]: layers[%u]=%p, layer=%p", - this, int(index), layers[index], layer); - layers.removeItemsAt(index); - lookup.removeItemsAt(keyIndex); - const size_t count = lookup.size(); - for (size_t i=0 ; i<count ; i++) { - if (lookup.valueAt(i) >= size_t(index)) { - lookup.editValueAt(i)--; - } - } - return index; - } - return NAME_NOT_FOUND; -} - -ssize_t SurfaceFlinger::LayerVector::reorder( - LayerBase* layer, - Vector<LayerBase*>::compar_t cmp) -{ - // XXX: it's a little lame. but oh well... - ssize_t err = remove(layer); - if (err >=0) - err = add(layer, cmp); - return err; -} - -// --------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -SurfaceFlinger::SurfaceFlinger() - : BnSurfaceComposer(), Thread(false), - mTransactionFlags(0), - mTransactionCount(0), - mBootTime(systemTime()), - mLastScheduledBroadcast(NULL), - mVisibleRegionsDirty(false), - mDeferReleaseConsole(false), - mFreezeDisplay(false), - mFreezeCount(0), - mDebugRegion(0), - mDebugCpu(0), - mDebugFps(0), - mDebugBackground(0), - mDebugNoBootAnimation(0), - mSyncObject(), - mDeplayedTransactionPending(0), - mConsoleSignals(0), - mSecureFrameBuffer(0) -{ - init(); -} - -void SurfaceFlinger::init() -{ - LOGI("SurfaceFlinger is starting"); - - // debugging stuff... - char value[PROPERTY_VALUE_MAX]; - property_get("debug.sf.showupdates", value, "0"); - mDebugRegion = atoi(value); - property_get("debug.sf.showcpu", value, "0"); - mDebugCpu = atoi(value); - property_get("debug.sf.showbackground", value, "0"); - mDebugBackground = atoi(value); - property_get("debug.sf.showfps", value, "0"); - mDebugFps = atoi(value); - property_get("debug.sf.nobootanimation", value, "0"); - mDebugNoBootAnimation = atoi(value); - - LOGI_IF(mDebugRegion, "showupdates enabled"); - LOGI_IF(mDebugCpu, "showcpu enabled"); - LOGI_IF(mDebugBackground, "showbackground enabled"); - LOGI_IF(mDebugFps, "showfps enabled"); - LOGI_IF(mDebugNoBootAnimation, "boot animation disabled"); -} - -SurfaceFlinger::~SurfaceFlinger() -{ - glDeleteTextures(1, &mWormholeTexName); - delete mOrientationAnimation; -} - -copybit_device_t* SurfaceFlinger::getBlitEngine() const -{ - return graphicPlane(0).displayHardware().getBlitEngine(); -} - -overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const -{ - return graphicPlane(0).displayHardware().getOverlayEngine(); -} - -sp<IMemory> SurfaceFlinger::getCblk() const -{ - return mServerCblkMemory; -} - -status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback, - gpu_info_t* gpu) -{ - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - status_t err = mGPU->request(pid, callback, gpu); - return err; -} - -status_t SurfaceFlinger::revokeGPU() -{ - return mGPU->friendlyRevoke(); -} - -sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection() -{ - Mutex::Autolock _l(mStateLock); - uint32_t token = mTokens.acquire(); - - Client* client = new Client(token, this); - if ((client == 0) || (client->ctrlblk == 0)) { - mTokens.release(token); - return 0; - } - status_t err = mClientsMap.add(token, client); - if (err < 0) { - delete client; - mTokens.release(token); - return 0; - } - sp<BClient> bclient = - new BClient(this, token, client->controlBlockMemory()); - return bclient; -} - -void SurfaceFlinger::destroyConnection(ClientID cid) -{ - Mutex::Autolock _l(mStateLock); - Client* const client = mClientsMap.valueFor(cid); - if (client) { - // free all the layers this client owns - const Vector<LayerBaseClient*>& layers = client->getLayers(); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - LayerBaseClient* const layer = layers[i]; - removeLayer_l(layer); - } - - // the resources associated with this client will be freed - // during the next transaction, after these surfaces have been - // properly removed from the screen - - // remove this client from our ClientID->Client mapping. - mClientsMap.removeItem(cid); - - // and add it to the list of disconnected clients - mDisconnectedClients.add(client); - - // request a transaction - setTransactionFlags(eTransactionNeeded); - } -} - -const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const -{ - LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy); - const GraphicPlane& plane(mGraphicPlanes[dpy]); - return plane; -} - -GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) -{ - return const_cast<GraphicPlane&>( - const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy)); -} - -void SurfaceFlinger::bootFinished() -{ - const nsecs_t now = systemTime(); - const nsecs_t duration = now - mBootTime; - LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); - if (mBootAnimation != 0) { - mBootAnimation->requestExit(); - mBootAnimation.clear(); - } -} - -void SurfaceFlinger::onFirstRef() -{ - run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY); - - // Wait for the main thread to be done with its initialization - mReadyToRunBarrier.wait(); -} - - -static inline uint16_t pack565(int r, int g, int b) { - return (r<<11)|(g<<5)|b; -} - -// this is defined in libGLES_CM.so -extern ISurfaceComposer* GLES_localSurfaceManager; - -status_t SurfaceFlinger::readyToRun() -{ - LOGI( "SurfaceFlinger's main thread ready to run. " - "Initializing graphics H/W..."); - - // create the shared control-block - mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY); - LOGE_IF(mServerHeap==0, "can't create shared memory dealer"); - - mServerCblkMemory = mServerHeap->allocate(4096); - LOGE_IF(mServerCblkMemory==0, "can't create shared control block"); - - mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer()); - LOGE_IF(mServerCblk==0, "can't get to shared control block's address"); - new(mServerCblk) surface_flinger_cblk_t; - - // get a reference to the GPU if we have one - mGPU = GPUFactory::getGPU(); - - // create the surface Heap manager, which manages the heaps - // (be it in RAM or VRAM) where surfaces are allocated - // We give 8 MB per client. - mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20); - - - GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this); - - // we only support one display currently - int dpy = 0; - - { - // initialize the main display - GraphicPlane& plane(graphicPlane(dpy)); - DisplayHardware* const hw = new DisplayHardware(this, dpy); - plane.setDisplayHardware(hw); - } - - // initialize primary screen - // (other display should be initialized in the same manner, but - // asynchronously, as they could come and go. None of this is supported - // yet). - const GraphicPlane& plane(graphicPlane(dpy)); - const DisplayHardware& hw = plane.displayHardware(); - const uint32_t w = hw.getWidth(); - const uint32_t h = hw.getHeight(); - const uint32_t f = hw.getFormat(); - hw.makeCurrent(); - - // initialize the shared control block - mServerCblk->connected |= 1<<dpy; - display_cblk_t* dcblk = mServerCblk->displays + dpy; - memset(dcblk, 0, sizeof(display_cblk_t)); - dcblk->w = w; - dcblk->h = h; - dcblk->format = f; - dcblk->orientation = ISurfaceComposer::eOrientationDefault; - dcblk->xdpi = hw.getDpiX(); - dcblk->ydpi = hw.getDpiY(); - dcblk->fps = hw.getRefreshRate(); - dcblk->density = hw.getDensity(); - asm volatile ("":::"memory"); - - // Initialize OpenGL|ES - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, 0); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glEnableClientState(GL_VERTEX_ARRAY); - glEnable(GL_SCISSOR_TEST); - glShadeModel(GL_FLAT); - glDisable(GL_DITHER); - glDisable(GL_CULL_FACE); - - const uint16_t g0 = pack565(0x0F,0x1F,0x0F); - const uint16_t g1 = pack565(0x17,0x2f,0x17); - const uint16_t textureData[4] = { g0, g1, g1, g0 }; - glGenTextures(1, &mWormholeTexName); - glBindTexture(GL_TEXTURE_2D, mWormholeTexName); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData); - - glViewport(0, 0, w, h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrthof(0, w, h, 0, 0, 1); - - LayerDim::initDimmer(this, w, h); - - mReadyToRunBarrier.open(); - - /* - * We're now ready to accept clients... - */ - - mOrientationAnimation = new OrientationAnimation(this); - - // start CPU gauge display - if (mDebugCpu) - mCpuGauge = new CPUGauge(this, ms2ns(500)); - - // the boot animation! - if (mDebugNoBootAnimation == false) - mBootAnimation = new BootAnimation(this); - - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Events Handler -#endif - -void SurfaceFlinger::waitForEvent() -{ - // wait for something to do - if (UNLIKELY(isFrozen())) { - // wait 5 seconds - int err = mSyncObject.wait(ms2ns(5000)); - if (err != NO_ERROR) { - if (isFrozen()) { - // we timed out and are still frozen - LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", - mFreezeDisplay, mFreezeCount); - mFreezeCount = 0; - } - } - } else { - mSyncObject.wait(); - } -} - -void SurfaceFlinger::signalEvent() { - mSyncObject.open(); -} - -void SurfaceFlinger::signal() const { - mSyncObject.open(); -} - -void SurfaceFlinger::signalDelayedEvent(nsecs_t delay) -{ - if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) { - sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay)); - delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY); - } -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Main loop -#endif - -bool SurfaceFlinger::threadLoop() -{ - waitForEvent(); - - // check for transactions - if (UNLIKELY(mConsoleSignals)) { - handleConsoleEvents(); - } - - if (LIKELY(mTransactionCount == 0)) { - // if we're in a global transaction, don't do anything. - const uint32_t mask = eTransactionNeeded | eTraversalNeeded; - uint32_t transactionFlags = getTransactionFlags(mask); - if (LIKELY(transactionFlags)) { - handleTransaction(transactionFlags); - } - } - - // post surfaces (if needed) - handlePageFlip(); - - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - if (LIKELY(hw.canDraw())) { - // repaint the framebuffer (if needed) - handleRepaint(); - - // release the clients before we flip ('cause flip might block) - unlockClients(); - executeScheduledBroadcasts(); - - // sample the cpu gauge - if (UNLIKELY(mDebugCpu)) { - handleDebugCpu(); - } - - postFramebuffer(); - } else { - // pretend we did the post - unlockClients(); - executeScheduledBroadcasts(); - usleep(16667); // 60 fps period - } - return true; -} - -void SurfaceFlinger::postFramebuffer() -{ - const bool skip = mOrientationAnimation->run(); - if (UNLIKELY(skip)) { - return; - } - - if (!mInvalidRegion.isEmpty()) { - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - - if (UNLIKELY(mDebugFps)) { - debugShowFPS(); - } - - hw.flip(mInvalidRegion); - - mInvalidRegion.clear(); - - if (Layer::deletedTextures.size()) { - glDeleteTextures( - Layer::deletedTextures.size(), - Layer::deletedTextures.array()); - Layer::deletedTextures.clear(); - } - } -} - -void SurfaceFlinger::handleConsoleEvents() -{ - // something to do with the console - const DisplayHardware& hw = graphicPlane(0).displayHardware(); - - int what = android_atomic_and(0, &mConsoleSignals); - if (what & eConsoleAcquired) { - hw.acquireScreen(); - } - - if (mDeferReleaseConsole && hw.canDraw()) { - // We got the release signal before the aquire signal - mDeferReleaseConsole = false; - revokeGPU(); - hw.releaseScreen(); - } - - if (what & eConsoleReleased) { - if (hw.canDraw()) { - revokeGPU(); - hw.releaseScreen(); - } else { - mDeferReleaseConsole = true; - } - } - - mDirtyRegion.set(hw.bounds()); -} - -void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) -{ - Mutex::Autolock _l(mStateLock); - - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - - /* - * Traversal of the children - * (perform the transaction for each of them if needed) - */ - - const bool layersNeedTransaction = transactionFlags & eTraversalNeeded; - if (layersNeedTransaction) { - for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = currentLayers[i]; - uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); - if (!trFlags) continue; - - const uint32_t flags = layer->doTransaction(0); - if (flags & Layer::eVisibleRegion) - mVisibleRegionsDirty = true; - - if (flags & Layer::eRestartTransaction) { - // restart the transaction, but back-off a little - layer->setTransactionFlags(eTransactionNeeded); - setTransactionFlags(eTraversalNeeded, ms2ns(8)); - } - } - } - - /* - * Perform our own transaction if needed - */ - - if (transactionFlags & eTransactionNeeded) { - if (mCurrentState.orientation != mDrawingState.orientation) { - // the orientation has changed, recompute all visible regions - // and invalidate everything. - - const int dpy = 0; - const int orientation = mCurrentState.orientation; - GraphicPlane& plane(graphicPlane(dpy)); - plane.setOrientation(orientation); - - // update the shared control block - const DisplayHardware& hw(plane.displayHardware()); - volatile display_cblk_t* dcblk = mServerCblk->displays + dpy; - dcblk->orientation = orientation; - if (orientation & eOrientationSwapMask) { - // 90 or 270 degrees orientation - dcblk->w = hw.getHeight(); - dcblk->h = hw.getWidth(); - } else { - dcblk->w = hw.getWidth(); - dcblk->h = hw.getHeight(); - } - - mVisibleRegionsDirty = true; - mDirtyRegion.set(hw.bounds()); - - mOrientationAnimation->onOrientationChanged(); - } - - if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { - // freezing or unfreezing the display -> trigger animation if needed - mFreezeDisplay = mCurrentState.freezeDisplay; - const nsecs_t now = systemTime(); - if (mFreezeDisplay) { - mFreezeDisplayTime = now; - } else { - //LOGD("Screen was frozen for %llu us", - // ns2us(now-mFreezeDisplayTime)); - } - } - - // some layers might have been removed, so - // we need to update the regions they're exposing. - size_t c = mRemovedLayers.size(); - if (c) { - mVisibleRegionsDirty = true; - } - - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) { - // layers have been added - mVisibleRegionsDirty = true; - } - - // get rid of all resources we don't need anymore - // (layers and clients) - free_resources_l(); - } - - commitTransaction(); -} - -sp<FreezeLock> SurfaceFlinger::getFreezeLock() const -{ - return new FreezeLock(const_cast<SurfaceFlinger *>(this)); -} - -void SurfaceFlinger::computeVisibleRegions( - LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion) -{ - const GraphicPlane& plane(graphicPlane(0)); - const Transform& planeTransform(plane.transform()); - - Region aboveOpaqueLayers; - Region aboveCoveredLayers; - Region dirty; - - bool secureFrameBuffer = false; - - size_t i = currentLayers.size(); - while (i--) { - LayerBase* const layer = currentLayers[i]; - layer->validateVisibility(planeTransform); - - // start with the whole surface at its current location - const Layer::State& s = layer->drawingState(); - const Rect bounds(layer->visibleBounds()); - - // handle hidden surfaces by setting the visible region to empty - Region opaqueRegion; - Region visibleRegion; - Region coveredRegion; - if (UNLIKELY((s.flags & ISurfaceComposer::eLayerHidden) || !s.alpha)) { - visibleRegion.clear(); - } else { - const bool translucent = layer->needsBlending(); - visibleRegion.set(bounds); - coveredRegion = visibleRegion; - - // Remove the transparent area from the visible region - if (translucent) { - visibleRegion.subtractSelf(layer->transparentRegionScreen); - } - - // compute the opaque region - if (s.alpha==255 && !translucent && layer->getOrientation()>=0) { - // the opaque region is the visible region - opaqueRegion = visibleRegion; - } - } - - // subtract the opaque region covered by the layers above us - visibleRegion.subtractSelf(aboveOpaqueLayers); - coveredRegion.andSelf(aboveCoveredLayers); - - // compute this layer's dirty region - if (layer->contentDirty) { - // we need to invalidate the whole region - dirty = visibleRegion; - // as well, as the old visible region - dirty.orSelf(layer->visibleRegionScreen); - layer->contentDirty = false; - } else { - // compute the exposed region - // dirty = what's visible now - what's wasn't covered before - // = what's visible now & what's was covered before - dirty = visibleRegion.intersect(layer->coveredRegionScreen); - } - dirty.subtractSelf(aboveOpaqueLayers); - - // accumulate to the screen dirty region - dirtyRegion.orSelf(dirty); - - // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer - aboveOpaqueLayers.orSelf(opaqueRegion); - aboveCoveredLayers.orSelf(bounds); - - // Store the visible region is screen space - layer->setVisibleRegion(visibleRegion); - layer->setCoveredRegion(coveredRegion); - - // If a secure layer is partially visible, lockdown the screen! - if (layer->isSecure() && !visibleRegion.isEmpty()) { - secureFrameBuffer = true; - } - } - - mSecureFrameBuffer = secureFrameBuffer; - opaqueRegion = aboveOpaqueLayers; -} - - -void SurfaceFlinger::commitTransaction() -{ - mDrawingState = mCurrentState; - mTransactionCV.signal(); -} - -void SurfaceFlinger::handlePageFlip() -{ - bool visibleRegions = mVisibleRegionsDirty; - LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ); - visibleRegions |= lockPageFlip(currentLayers); - - const DisplayHardware& hw = graphicPlane(0).displayHardware(); - const Region screenRegion(hw.bounds()); - if (visibleRegions) { - Region opaqueRegion; - computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion); - mWormholeRegion = screenRegion.subtract(opaqueRegion); - mVisibleRegionsDirty = false; - } - - unlockPageFlip(currentLayers); - mDirtyRegion.andSelf(screenRegion); -} - -bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers) -{ - bool recomputeVisibleRegions = false; - size_t count = currentLayers.size(); - LayerBase* const* layers = currentLayers.array(); - for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = layers[i]; - layer->lockPageFlip(recomputeVisibleRegions); - } - return recomputeVisibleRegions; -} - -void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) -{ - const GraphicPlane& plane(graphicPlane(0)); - const Transform& planeTransform(plane.transform()); - size_t count = currentLayers.size(); - LayerBase* const* layers = currentLayers.array(); - for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = layers[i]; - layer->unlockPageFlip(planeTransform, mDirtyRegion); - } -} - -void SurfaceFlinger::handleRepaint() -{ - // set the frame buffer - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - if (UNLIKELY(mDebugRegion)) { - debugFlashRegions(); - } - - // compute the invalid region - mInvalidRegion.orSelf(mDirtyRegion); - - uint32_t flags = hw.getFlags(); - if (flags & DisplayHardware::BUFFER_PRESERVED) { - // here we assume DisplayHardware::flip()'s implementation - // performs the copy-back optimization. - } else { - if (flags & DisplayHardware::UPDATE_ON_DEMAND) { - // we need to fully redraw the part that will be updated - mDirtyRegion.set(mInvalidRegion.bounds()); - } else { - // we need to redraw everything - mDirtyRegion.set(hw.bounds()); - mInvalidRegion = mDirtyRegion; - } - } - - // compose all surfaces - composeSurfaces(mDirtyRegion); - - // clear the dirty regions - mDirtyRegion.clear(); -} - -void SurfaceFlinger::composeSurfaces(const Region& dirty) -{ - if (UNLIKELY(!mWormholeRegion.isEmpty())) { - // should never happen unless the window manager has a bug - // draw something... - drawWormhole(); - } - const SurfaceFlinger& flinger(*this); - const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); - const size_t count = drawingLayers.size(); - LayerBase const* const* const layers = drawingLayers.array(); - for (size_t i=0 ; i<count ; ++i) { - LayerBase const * const layer = layers[i]; - const Region& visibleRegion(layer->visibleRegionScreen); - if (!visibleRegion.isEmpty()) { - const Region clip(dirty.intersect(visibleRegion)); - if (!clip.isEmpty()) { - layer->draw(clip); - } - } - } -} - -void SurfaceFlinger::unlockClients() -{ - const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); - const size_t count = drawingLayers.size(); - LayerBase* const* const layers = drawingLayers.array(); - for (size_t i=0 ; i<count ; ++i) { - LayerBase* const layer = layers[i]; - layer->finishPageFlip(); - } -} - -void SurfaceFlinger::scheduleBroadcast(Client* client) -{ - if (mLastScheduledBroadcast != client) { - mLastScheduledBroadcast = client; - mScheduledBroadcasts.add(client); - } -} - -void SurfaceFlinger::executeScheduledBroadcasts() -{ - SortedVector<Client*>& list = mScheduledBroadcasts; - size_t count = list.size(); - while (count--) { - per_client_cblk_t* const cblk = list[count]->ctrlblk; - if (cblk->lock.tryLock() == NO_ERROR) { - cblk->cv.broadcast(); - list.removeAt(count); - cblk->lock.unlock(); - } else { - // schedule another round - LOGW("executeScheduledBroadcasts() skipped, " - "contention on the client. We'll try again later..."); - signalDelayedEvent(ms2ns(4)); - } - } - mLastScheduledBroadcast = 0; -} - -void SurfaceFlinger::handleDebugCpu() -{ - Mutex::Autolock _l(mDebugLock); - if (mCpuGauge != 0) - mCpuGauge->sample(); -} - -void SurfaceFlinger::debugFlashRegions() -{ - if (UNLIKELY(!mDirtyRegion.isRect())) { - // TODO: do this only if we don't have preserving - // swapBuffer. If we don't have update-on-demand, - // redraw everything. - composeSurfaces(Region(mDirtyRegion.bounds())); - } - - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - - glColor4x(0x10000, 0, 0x10000, 0x10000); - - Rect r; - Region::iterator iterator(mDirtyRegion); - while (iterator.iterate(&r)) { - GLfloat vertices[][2] = { - { r.left, r.top }, - { r.left, r.bottom }, - { r.right, r.bottom }, - { r.right, r.top } - }; - glVertexPointer(2, GL_FLOAT, 0, vertices); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - hw.flip(mDirtyRegion.merge(mInvalidRegion)); - mInvalidRegion.clear(); - - if (mDebugRegion > 1) - usleep(mDebugRegion * 1000); - - glEnable(GL_SCISSOR_TEST); - //mDirtyRegion.dump("mDirtyRegion"); -} - -void SurfaceFlinger::drawWormhole() const -{ - const Region region(mWormholeRegion.intersect(mDirtyRegion)); - if (region.isEmpty()) - return; - - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const int32_t width = hw.getWidth(); - const int32_t height = hw.getHeight(); - - glDisable(GL_BLEND); - glDisable(GL_DITHER); - - if (LIKELY(!mDebugBackground)) { - glClearColorx(0,0,0,0); - Rect r; - Region::iterator iterator(region); - while (iterator.iterate(&r)) { - const GLint sy = height - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glClear(GL_COLOR_BUFFER_BIT); - } - } else { - const GLshort vertices[][2] = { { 0, 0 }, { width, 0 }, - { width, height }, { 0, height } }; - const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } }; - glVertexPointer(2, GL_SHORT, 0, vertices); - glTexCoordPointer(2, GL_SHORT, 0, tcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, mWormholeTexName); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1); - Rect r; - Region::iterator iterator(region); - while (iterator.iterate(&r)) { - const GLint sy = height - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } -} - -void SurfaceFlinger::debugShowFPS() const -{ - static int mFrameCount; - static int mLastFrameCount = 0; - static nsecs_t mLastFpsTime = 0; - static float mFps = 0; - mFrameCount++; - nsecs_t now = systemTime(); - nsecs_t diff = now - mLastFpsTime; - if (diff > ms2ns(250)) { - mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; - mLastFpsTime = now; - mLastFrameCount = mFrameCount; - } - // XXX: mFPS has the value we want - } - -status_t SurfaceFlinger::addLayer(LayerBase* layer) -{ - Mutex::Autolock _l(mStateLock); - addLayer_l(layer); - setTransactionFlags(eTransactionNeeded|eTraversalNeeded); - return NO_ERROR; -} - -status_t SurfaceFlinger::removeLayer(LayerBase* layer) -{ - Mutex::Autolock _l(mStateLock); - removeLayer_l(layer); - setTransactionFlags(eTransactionNeeded); - return NO_ERROR; -} - -status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer) -{ - layer->forceVisibilityTransaction(); - setTransactionFlags(eTraversalNeeded); - return NO_ERROR; -} - -status_t SurfaceFlinger::addLayer_l(LayerBase* layer) -{ - ssize_t i = mCurrentState.layersSortedByZ.add( - layer, &LayerBase::compareCurrentStateZ); - LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer); - if (lbc) { - mLayerMap.add(lbc->serverIndex(), lbc); - } - mRemovedLayers.remove(layer); - return NO_ERROR; -} - -status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase) -{ - ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); - if (index >= 0) { - mRemovedLayers.add(layerBase); - LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase); - if (layer) { - mLayerMap.removeItem(layer->serverIndex()); - } - return NO_ERROR; - } - // it's possible that we don't find a layer, because it might - // have been destroyed already -- this is not technically an error - // from the user because there is a race between destroySurface, - // destroyclient and destroySurface-from-a-transaction. - return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index; -} - -void SurfaceFlinger::free_resources_l() -{ - // Destroy layers that were removed - destroy_all_removed_layers_l(); - - // free resources associated with disconnected clients - SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts); - Vector<Client*>& disconnectedClients(mDisconnectedClients); - const size_t count = disconnectedClients.size(); - for (size_t i=0 ; i<count ; i++) { - Client* client = disconnectedClients[i]; - // if this client is the scheduled broadcast list, - // remove it from there (and we don't need to signal it - // since it is dead). - int32_t index = scheduledBroadcasts.indexOf(client); - if (index >= 0) { - scheduledBroadcasts.removeItemsAt(index); - } - mTokens.release(client->cid); - delete client; - } - disconnectedClients.clear(); -} - -void SurfaceFlinger::destroy_all_removed_layers_l() -{ - size_t c = mRemovedLayers.size(); - while (c--) { - LayerBase* const removed_layer = mRemovedLayers[c]; - - LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0, - "layer %p removed but still in the current state list", - removed_layer); - - delete removed_layer; - } - mRemovedLayers.clear(); -} - - -uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) -{ - return android_atomic_and(~flags, &mTransactionFlags) & flags; -} - -uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay) -{ - uint32_t old = android_atomic_or(flags, &mTransactionFlags); - if ((old & flags)==0) { // wake the server up - if (delay > 0) { - signalDelayedEvent(delay); - } else { - signalEvent(); - } - } - return old; -} - -void SurfaceFlinger::openGlobalTransaction() -{ - android_atomic_inc(&mTransactionCount); -} - -void SurfaceFlinger::closeGlobalTransaction() -{ - if (android_atomic_dec(&mTransactionCount) == 1) { - signalEvent(); - } -} - -status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags) -{ - if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) - return BAD_VALUE; - - Mutex::Autolock _l(mStateLock); - mCurrentState.freezeDisplay = 1; - setTransactionFlags(eTransactionNeeded); - - // flags is intended to communicate some sort of animation behavior - // (for instance fadding) - return NO_ERROR; -} - -status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags) -{ - if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) - return BAD_VALUE; - - Mutex::Autolock _l(mStateLock); - mCurrentState.freezeDisplay = 0; - setTransactionFlags(eTransactionNeeded); - - // flags is intended to communicate some sort of animation behavior - // (for instance fadding) - return NO_ERROR; -} - -int SurfaceFlinger::setOrientation(DisplayID dpy, int orientation) -{ - if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) - return BAD_VALUE; - - Mutex::Autolock _l(mStateLock); - if (mCurrentState.orientation != orientation) { - if (uint32_t(orientation)<=eOrientation270 || orientation==42) { - mCurrentState.orientation = orientation; - setTransactionFlags(eTransactionNeeded); - mTransactionCV.wait(mStateLock); - } else { - orientation = BAD_VALUE; - } - } - return orientation; -} - -sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, - ISurfaceFlingerClient::surface_data_t* params, - DisplayID d, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags) -{ - LayerBaseClient* layer = 0; - sp<LayerBaseClient::Surface> surfaceHandle; - Mutex::Autolock _l(mStateLock); - Client* const c = mClientsMap.valueFor(clientId); - if (UNLIKELY(!c)) { - LOGE("createSurface() failed, client not found (id=%d)", clientId); - return surfaceHandle; - } - - //LOGD("createSurface for pid %d (%d x %d)", pid, w, h); - int32_t id = c->generateId(pid); - if (uint32_t(id) >= NUM_LAYERS_MAX) { - LOGE("createSurface() failed, generateId = %d", id); - return surfaceHandle; - } - - switch (flags & eFXSurfaceMask) { - case eFXSurfaceNormal: - if (UNLIKELY(flags & ePushBuffers)) { - layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags); - } else { - layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags); - } - break; - case eFXSurfaceBlur: - layer = createBlurSurfaceLocked(c, d, id, w, h, flags); - break; - case eFXSurfaceDim: - layer = createDimSurfaceLocked(c, d, id, w, h, flags); - break; - } - - if (layer) { - setTransactionFlags(eTransactionNeeded); - surfaceHandle = layer->getSurface(); - if (surfaceHandle != 0) - surfaceHandle->getSurfaceData(params); - } - - return surfaceHandle; -} - -LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked( - Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) -{ - // initialize the surfaces - switch (format) { // TODO: take h/w into account - case PIXEL_FORMAT_TRANSPARENT: - case PIXEL_FORMAT_TRANSLUCENT: - format = PIXEL_FORMAT_RGBA_8888; - break; - case PIXEL_FORMAT_OPAQUE: - format = PIXEL_FORMAT_RGB_565; - break; - } - - Layer* layer = new Layer(this, display, client, id); - status_t err = layer->setBuffers(client, w, h, format, flags); - if (LIKELY(err == NO_ERROR)) { - layer->initStates(w, h, flags); - addLayer_l(layer); - } else { - LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err)); - delete layer; - return 0; - } - return layer; -} - -LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked( - Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, uint32_t flags) -{ - LayerBlur* layer = new LayerBlur(this, display, client, id); - layer->initStates(w, h, flags); - addLayer_l(layer); - return layer; -} - -LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked( - Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, uint32_t flags) -{ - LayerDim* layer = new LayerDim(this, display, client, id); - layer->initStates(w, h, flags); - addLayer_l(layer); - return layer; -} - -LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked( - Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, uint32_t flags) -{ - LayerBuffer* layer = new LayerBuffer(this, display, client, id); - layer->initStates(w, h, flags); - addLayer_l(layer); - return layer; -} - -status_t SurfaceFlinger::destroySurface(SurfaceID index) -{ - Mutex::Autolock _l(mStateLock); - LayerBaseClient* const layer = getLayerUser_l(index); - status_t err = removeLayer_l(layer); - if (err < 0) - return err; - setTransactionFlags(eTransactionNeeded); - return NO_ERROR; -} - -status_t SurfaceFlinger::setClientState( - ClientID cid, - int32_t count, - const layer_state_t* states) -{ - Mutex::Autolock _l(mStateLock); - uint32_t flags = 0; - cid <<= 16; - for (int i=0 ; i<count ; i++) { - const layer_state_t& s = states[i]; - LayerBaseClient* layer = getLayerUser_l(s.surface | cid); - if (layer) { - const uint32_t what = s.what; - // check if it has been destroyed first - if (what & eDestroyed) { - if (removeLayer_l(layer) == NO_ERROR) { - flags |= eTransactionNeeded; - // we skip everything else... well, no, not really - // we skip ONLY that transaction. - continue; - } - } - if (what & ePositionChanged) { - if (layer->setPosition(s.x, s.y)) - flags |= eTraversalNeeded; - } - if (what & eLayerChanged) { - if (layer->setLayer(s.z)) { - mCurrentState.layersSortedByZ.reorder( - layer, &Layer::compareCurrentStateZ); - // we need traversal (state changed) - // AND transaction (list changed) - flags |= eTransactionNeeded|eTraversalNeeded; - } - } - if (what & eSizeChanged) { - if (layer->setSize(s.w, s.h)) - flags |= eTraversalNeeded; - } - if (what & eAlphaChanged) { - if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) - flags |= eTraversalNeeded; - } - if (what & eMatrixChanged) { - if (layer->setMatrix(s.matrix)) - flags |= eTraversalNeeded; - } - if (what & eTransparentRegionChanged) { - if (layer->setTransparentRegionHint(s.transparentRegion)) - flags |= eTraversalNeeded; - } - if (what & eVisibilityChanged) { - if (layer->setFlags(s.flags, s.mask)) - flags |= eTraversalNeeded; - } - } - } - if (flags) { - setTransactionFlags(flags); - } - return NO_ERROR; -} - -LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const -{ - return mLayerMap.valueFor(s); -} - -void SurfaceFlinger::screenReleased(int dpy) -{ - // this may be called by a signal handler, we can't do too much in here - android_atomic_or(eConsoleReleased, &mConsoleSignals); - signalEvent(); -} - -void SurfaceFlinger::screenAcquired(int dpy) -{ - // this may be called by a signal handler, we can't do too much in here - android_atomic_or(eConsoleAcquired, &mConsoleSignals); - signalEvent(); -} - -status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 1024; - char buffer[SIZE]; - String8 result; - if (checkCallingPermission( - String16("android.permission.DUMP")) == false) - { // not allowed - snprintf(buffer, SIZE, "Permission Denial: " - "can't dump SurfaceFlinger from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - result.append(buffer); - } else { - Mutex::Autolock _l(mStateLock); - size_t s = mClientsMap.size(); - char name[64]; - for (size_t i=0 ; i<s ; i++) { - Client* client = mClientsMap.valueAt(i); - sprintf(name, " Client (id=0x%08x)", client->cid); - client->dump(name); - } - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - /*** LayerBase ***/ - LayerBase const * const layer = currentLayers[i]; - const Layer::State& s = layer->drawingState(); - snprintf(buffer, SIZE, - "+ %s %p\n" - " " - "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " - "needsBlending=%1d, invalidate=%1d, " - "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", - layer->getTypeID(), layer, - s.z, layer->tx(), layer->ty(), s.w, s.h, - layer->needsBlending(), layer->contentDirty, - s.alpha, s.flags, - s.transform[0], s.transform[1], - s.transform[2], s.transform[3]); - result.append(buffer); - buffer[0] = 0; - /*** LayerBaseClient ***/ - LayerBaseClient* const lbc = - LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer); - if (lbc) { - snprintf(buffer, SIZE, - " " - "id=0x%08x, client=0x%08x, identity=%u\n", - lbc->clientIndex(), lbc->client ? lbc->client->cid : 0, - lbc->getIdentity()); - } - result.append(buffer); - buffer[0] = 0; - /*** Layer ***/ - Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer); - if (l) { - const LayerBitmap& buf0(l->getBuffer(0)); - const LayerBitmap& buf1(l->getBuffer(1)); - snprintf(buffer, SIZE, - " " - "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d," - " freezeLock=%p, swapState=0x%08x\n", - l->pixelFormat(), - buf0.width(), buf0.height(), buf0.stride(), - buf1.width(), buf1.height(), buf1.stride(), - l->getTextureName(), l->getFreezeLock().get(), - l->lcblk->swapState); - } - result.append(buffer); - buffer[0] = 0; - s.transparentRegion.dump(result, "transparentRegion"); - layer->transparentRegionScreen.dump(result, "transparentRegionScreen"); - layer->visibleRegionScreen.dump(result, "visibleRegionScreen"); - } - mWormholeRegion.dump(result, "WormholeRegion"); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - snprintf(buffer, SIZE, - " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n", - mFreezeDisplay?"yes":"no", mFreezeCount, - mCurrentState.orientation, hw.canDraw()); - result.append(buffer); - - sp<AllocatorInterface> allocator; - if (mGPU != 0) { - snprintf(buffer, SIZE, " GPU owner: %d\n", mGPU->getOwner()); - result.append(buffer); - allocator = mGPU->getAllocator(); - if (allocator != 0) { - allocator->dump(result, "GPU Allocator"); - } - } - allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM); - if (allocator != 0) { - allocator->dump(result, "PMEM Allocator"); - } - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t SurfaceFlinger::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch (code) { - case CREATE_CONNECTION: - case OPEN_GLOBAL_TRANSACTION: - case CLOSE_GLOBAL_TRANSACTION: - case SET_ORIENTATION: - case FREEZE_DISPLAY: - case UNFREEZE_DISPLAY: - case BOOT_FINISHED: - case REVOKE_GPU: - { - // codes that require permission check - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int self_pid = getpid(); - if (UNLIKELY(pid != self_pid)) { - // we're called from a different process, do the real check - if (!checkCallingPermission( - String16("android.permission.ACCESS_SURFACE_FLINGER"))) - { - const int uid = ipc->getCallingUid(); - LOGE("Permission Denial: " - "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); - return PERMISSION_DENIED; - } - } - } - } - - status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags); - if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) { - // HARDWARE_TEST stuff... - if (UNLIKELY(checkCallingPermission( - String16("android.permission.HARDWARE_TEST")) == false)) - { // not allowed - LOGE("Permission Denial: pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - return PERMISSION_DENIED; - } - int n; - switch (code) { - case 1000: // SHOW_CPU - n = data.readInt32(); - mDebugCpu = n ? 1 : 0; - if (mDebugCpu) { - if (mCpuGauge == 0) { - mCpuGauge = new CPUGauge(this, ms2ns(500)); - } - } else { - if (mCpuGauge != 0) { - mCpuGauge->requestExitAndWait(); - Mutex::Autolock _l(mDebugLock); - mCpuGauge.clear(); - } - } - return NO_ERROR; - case 1001: // SHOW_FPS - n = data.readInt32(); - mDebugFps = n ? 1 : 0; - return NO_ERROR; - case 1002: // SHOW_UPDATES - n = data.readInt32(); - mDebugRegion = n ? n : (mDebugRegion ? 0 : 1); - return NO_ERROR; - case 1003: // SHOW_BACKGROUND - n = data.readInt32(); - mDebugBackground = n ? 1 : 0; - return NO_ERROR; - case 1004:{ // repaint everything - Mutex::Autolock _l(mStateLock); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe - signalEvent(); - } - return NO_ERROR; - case 1005: // ask GPU revoke - mGPU->friendlyRevoke(); - return NO_ERROR; - case 1006: // revoke GPU - mGPU->unconditionalRevoke(); - return NO_ERROR; - case 1007: // set mFreezeCount - mFreezeCount = data.readInt32(); - return NO_ERROR; - case 1010: // interrogate. - reply->writeInt32(mDebugCpu); - reply->writeInt32(0); - reply->writeInt32(mDebugRegion); - reply->writeInt32(mDebugBackground); - return NO_ERROR; - case 1013: { - Mutex::Autolock _l(mStateLock); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - reply->writeInt32(hw.getPageFlipCount()); - } - return NO_ERROR; - } - } - return err; -} - -// --------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger) - : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) -{ - mSharedHeapAllocator = getSurfaceHeapManager()->createHeap(); - const int pgsize = getpagesize(); - const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1)); - mCblkHeap = new MemoryDealer(cblksize); - mCblkMemory = mCblkHeap->allocate(cblksize); - if (mCblkMemory != 0) { - ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer()); - if (ctrlblk) { // construct the shared structure in-place. - new(ctrlblk) per_client_cblk_t; - } - } -} - -Client::~Client() { - if (ctrlblk) { - const int pgsize = getpagesize(); - ctrlblk->~per_client_cblk_t(); // destroy our shared-structure. - } -} - -const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const { - return mFlinger->getSurfaceHeapManager(); -} - -int32_t Client::generateId(int pid) -{ - const uint32_t i = clz( ~mBitmap ); - if (i >= NUM_LAYERS_MAX) { - return NO_MEMORY; - } - mPid = pid; - mInUse.add(uint8_t(i)); - mBitmap |= 1<<(31-i); - return i; -} -status_t Client::bindLayer(LayerBaseClient* layer, int32_t id) -{ - ssize_t idx = mInUse.indexOf(id); - if (idx < 0) - return NAME_NOT_FOUND; - return mLayers.insertAt(layer, idx); -} -void Client::free(int32_t id) -{ - ssize_t idx = mInUse.remove(uint8_t(id)); - if (idx >= 0) { - mBitmap &= ~(1<<(31-id)); - mLayers.removeItemsAt(idx); - } -} - -sp<MemoryDealer> Client::createAllocator(uint32_t flags) -{ - sp<MemoryDealer> allocator; - allocator = getSurfaceHeapManager()->createHeap( - flags, getClientPid(), mSharedHeapAllocator); - return allocator; -} - -bool Client::isValid(int32_t i) const { - return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i))); -} -const uint8_t* Client::inUseArray() const { - return mInUse.array(); -} -size_t Client::numActiveLayers() const { - return mInUse.size(); -} -LayerBaseClient* Client::getLayerUser(int32_t i) const { - ssize_t idx = mInUse.indexOf(uint8_t(i)); - if (idx<0) return 0; - return mLayers[idx]; -} - -void Client::dump(const char* what) -{ -} - -// --------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk) - : mId(cid), mFlinger(flinger), mCblk(cblk) -{ -} - -BClient::~BClient() { - // destroy all resources attached to this client - mFlinger->destroyConnection(mId); -} - -void BClient::getControlBlocks(sp<IMemory>* ctrl) const { - *ctrl = mCblk; -} - -sp<ISurface> BClient::createSurface( - ISurfaceFlingerClient::surface_data_t* params, int pid, - DisplayID display, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags) -{ - return mFlinger->createSurface(mId, pid, params, display, w, h, format, flags); -} - -status_t BClient::destroySurface(SurfaceID sid) -{ - sid |= (mId << 16); // add the client-part to id - return mFlinger->destroySurface(sid); -} - -status_t BClient::setState(int32_t count, const layer_state_t* states) -{ - return mFlinger->setClientState(mId, count, states); -} - -// --------------------------------------------------------------------------- - -GraphicPlane::GraphicPlane() - : mHw(0) -{ -} - -GraphicPlane::~GraphicPlane() { - delete mHw; -} - -bool GraphicPlane::initialized() const { - return mHw ? true : false; -} - -void GraphicPlane::setDisplayHardware(DisplayHardware *hw) { - mHw = hw; -} - -void GraphicPlane::setTransform(const Transform& tr) { - mTransform = tr; - mGlobalTransform = mOrientationTransform * mTransform; -} - -status_t GraphicPlane::orientationToTransfrom( - int orientation, int w, int h, Transform* tr) -{ - float a, b, c, d, x, y; - switch (orientation) { - case ISurfaceComposer::eOrientationDefault: - a=1; b=0; c=0; d=1; x=0; y=0; - break; - case ISurfaceComposer::eOrientation90: - a=0; b=-1; c=1; d=0; x=w; y=0; - break; - case ISurfaceComposer::eOrientation180: - a=-1; b=0; c=0; d=-1; x=w; y=h; - break; - case ISurfaceComposer::eOrientation270: - a=0; b=1; c=-1; d=0; x=0; y=h; - break; - default: - return BAD_VALUE; - } - tr->set(a, b, c, d); - tr->set(x, y); - return NO_ERROR; -} - -status_t GraphicPlane::setOrientation(int orientation) -{ - const DisplayHardware& hw(displayHardware()); - const float w = hw.getWidth(); - const float h = hw.getHeight(); - - if (orientation == ISurfaceComposer::eOrientationDefault) { - // make sure the default orientation is optimal - mOrientationTransform.reset(); - mGlobalTransform = mTransform; - return NO_ERROR; - } - - // If the rotation can be handled in hardware, this is where - // the magic should happen. - if (UNLIKELY(orientation == 42)) { - float a, b, c, d, x, y; - const float r = (3.14159265f / 180.0f) * 42.0f; - const float si = sinf(r); - const float co = cosf(r); - a=co; b=-si; c=si; d=co; - x = si*(h*0.5f) + (1-co)*(w*0.5f); - y =-si*(w*0.5f) + (1-co)*(h*0.5f); - mOrientationTransform.set(a, b, c, d); - mOrientationTransform.set(x, y); - } else { - GraphicPlane::orientationToTransfrom(orientation, w, h, - &mOrientationTransform); - } - - mGlobalTransform = mOrientationTransform * mTransform; - return NO_ERROR; -} - -const DisplayHardware& GraphicPlane::displayHardware() const { - return *mHw; -} - -const Transform& GraphicPlane::transform() const { - return mGlobalTransform; -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h deleted file mode 100644 index f7d7764..0000000 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_SURFACE_FLINGER_H -#define ANDROID_SURFACE_FLINGER_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/SortedVector.h> -#include <utils/KeyedVector.h> -#include <utils/threads.h> -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/MemoryDealer.h> - -#include <ui/PixelFormat.h> -#include <ui/ISurfaceComposer.h> -#include <ui/ISurfaceFlingerClient.h> - -#include <private/ui/SharedState.h> -#include <private/ui/LayerState.h> -#include <private/ui/SurfaceFlingerSynchro.h> - -#include "Barrier.h" -#include "BootAnimation.h" -#include "CPUGauge.h" -#include "Layer.h" -#include "Tokenizer.h" - -struct copybit_device_t; -struct overlay_device_t; - -namespace android { - -// --------------------------------------------------------------------------- - -class Client; -class BClient; -class DisplayHardware; -class FreezeLock; -class GPUHardwareInterface; -class IGPUCallback; -class Layer; -class LayerBuffer; -class LayerOrientationAnim; -class OrientationAnimation; -class SurfaceHeapManager; - -typedef int32_t ClientID; - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// --------------------------------------------------------------------------- - -class Client -{ -public: - Client(ClientID cid, const sp<SurfaceFlinger>& flinger); - ~Client(); - - int32_t generateId(int pid); - void free(int32_t id); - status_t bindLayer(LayerBaseClient* layer, int32_t id); - sp<MemoryDealer> createAllocator(uint32_t memory_type); - - inline bool isValid(int32_t i) const; - inline const uint8_t* inUseArray() const; - inline size_t numActiveLayers() const; - LayerBaseClient* getLayerUser(int32_t i) const; - const Vector<LayerBaseClient*>& getLayers() const { return mLayers; } - const sp<IMemory>& controlBlockMemory() const { return mCblkMemory; } - void dump(const char* what); - const sp<SurfaceHeapManager>& getSurfaceHeapManager() const; - - // pointer to this client's control block - per_client_cblk_t* ctrlblk; - ClientID cid; - - -private: - int getClientPid() const { return mPid; } - - int mPid; - uint32_t mBitmap; - SortedVector<uint8_t> mInUse; - Vector<LayerBaseClient*> mLayers; - sp<MemoryDealer> mCblkHeap; - sp<SurfaceFlinger> mFlinger; - sp<MemoryDealer> mSharedHeapAllocator; - sp<MemoryDealer> mPMemAllocator; - sp<IMemory> mCblkMemory; -}; - -// --------------------------------------------------------------------------- - -class GraphicPlane -{ -public: - static status_t orientationToTransfrom(int orientation, int w, int h, - Transform* tr); - - GraphicPlane(); - ~GraphicPlane(); - - bool initialized() const; - - void setDisplayHardware(DisplayHardware *); - void setTransform(const Transform& tr); - status_t setOrientation(int orientation); - - const DisplayHardware& displayHardware() const; - const Transform& transform() const; -private: - GraphicPlane(const GraphicPlane&); - GraphicPlane operator = (const GraphicPlane&); - - DisplayHardware* mHw; - Transform mTransform; - Transform mOrientationTransform; - Transform mGlobalTransform; -}; - -// --------------------------------------------------------------------------- - -enum { - eTransactionNeeded = 0x01, - eTraversalNeeded = 0x02 -}; - -class SurfaceFlinger : public BnSurfaceComposer, protected Thread -{ -public: - static void instantiate(); - static void shutdown(); - - SurfaceFlinger(); - virtual ~SurfaceFlinger(); - void init(); - - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - - virtual status_t dump(int fd, const Vector<String16>& args); - - // ISurfaceComposer interface - virtual sp<ISurfaceFlingerClient> createConnection(); - virtual sp<IMemory> getCblk() const; - virtual void bootFinished(); - virtual void openGlobalTransaction(); - virtual void closeGlobalTransaction(); - virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags); - virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); - virtual int setOrientation(DisplayID dpy, int orientation); - virtual void signal() const; - virtual status_t requestGPU(const sp<IGPUCallback>& callback, - gpu_info_t* gpu); - virtual status_t revokeGPU(); - - void screenReleased(DisplayID dpy); - void screenAcquired(DisplayID dpy); - - const sp<SurfaceHeapManager>& getSurfaceHeapManager() const { - return mSurfaceHeapManager; - } - - const sp<GPUHardwareInterface>& getGPU() const { - return mGPU; - } - - copybit_device_t* getBlitEngine() const; - overlay_control_device_t* getOverlayEngine() const; - - - status_t removeLayer(LayerBase* layer); - status_t addLayer(LayerBase* layer); - status_t invalidateLayerVisibility(LayerBase* layer); - -private: - friend class BClient; - friend class LayerBase; - friend class LayerBuffer; - friend class LayerBaseClient; - friend class Layer; - friend class LayerBlur; - - sp<ISurface> createSurface(ClientID client, int pid, - ISurfaceFlingerClient::surface_data_t* params, - DisplayID display, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags); - - LayerBaseClient* createNormalSurfaceLocked(Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); - - LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, uint32_t flags); - - LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, uint32_t flags); - - LayerBaseClient* createPushBuffersSurfaceLocked(Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, uint32_t flags); - - status_t destroySurface(SurfaceID surface_id); - status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states); - - - class LayerVector { - public: - inline LayerVector() { } - LayerVector(const LayerVector&); - inline size_t size() const { return layers.size(); } - inline LayerBase*const* array() const { return layers.array(); } - ssize_t add(LayerBase*, Vector<LayerBase*>::compar_t); - ssize_t remove(LayerBase*); - ssize_t reorder(LayerBase*, Vector<LayerBase*>::compar_t); - ssize_t indexOf(LayerBase* key, size_t guess=0) const; - inline LayerBase* operator [] (size_t i) const { return layers[i]; } - private: - KeyedVector<LayerBase*, size_t> lookup; - Vector<LayerBase*> layers; - }; - - struct State { - State() { - orientation = ISurfaceComposer::eOrientationDefault; - freezeDisplay = 0; - } - LayerVector layersSortedByZ; - uint8_t orientation; - uint8_t freezeDisplay; - }; - - class DelayedTransaction : public Thread - { - friend class SurfaceFlinger; - sp<SurfaceFlinger> mFlinger; - nsecs_t mDelay; - public: - DelayedTransaction(const sp<SurfaceFlinger>& flinger, nsecs_t delay) - : Thread(false), mFlinger(flinger), mDelay(delay) { - } - virtual bool threadLoop() { - usleep(mDelay / 1000); - if (android_atomic_and(~1, - &mFlinger->mDeplayedTransactionPending) == 1) { - mFlinger->signalEvent(); - } - return false; - } - }; - - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void onFirstRef(); - - const GraphicPlane& graphicPlane(int dpy) const; - GraphicPlane& graphicPlane(int dpy); - - void waitForEvent(); - void signalEvent(); - void signalDelayedEvent(nsecs_t delay); - - void handleConsoleEvents(); - void handleTransaction(uint32_t transactionFlags); - - void computeVisibleRegions( - LayerVector& currentLayers, - Region& dirtyRegion, - Region& wormholeRegion); - - void handlePageFlip(); - bool lockPageFlip(const LayerVector& currentLayers); - void unlockPageFlip(const LayerVector& currentLayers); - void handleRepaint(); - void handleDebugCpu(); - void scheduleBroadcast(Client* client); - void executeScheduledBroadcasts(); - void postFramebuffer(); - void composeSurfaces(const Region& dirty); - void unlockClients(); - - - void destroyConnection(ClientID cid); - LayerBaseClient* getLayerUser_l(SurfaceID index) const; - status_t addLayer_l(LayerBase* layer); - status_t removeLayer_l(LayerBase* layer); - void destroy_all_removed_layers_l(); - void free_resources_l(); - - uint32_t getTransactionFlags(uint32_t flags); - uint32_t setTransactionFlags(uint32_t flags, nsecs_t delay = 0); - void commitTransaction(); - - - friend class FreezeLock; - sp<FreezeLock> getFreezeLock() const; - inline void incFreezeCount() { mFreezeCount++; } - inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; } - inline bool hasFreezeRequest() const { return mFreezeDisplay; } - inline bool isFrozen() const { - return mFreezeDisplay || mFreezeCount>0; - } - - - void debugFlashRegions(); - void debugShowFPS() const; - void drawWormhole() const; - - // access must be protected by mStateLock - mutable Mutex mStateLock; - State mCurrentState; - State mDrawingState; - volatile int32_t mTransactionFlags; - volatile int32_t mTransactionCount; - Condition mTransactionCV; - - // protected by mStateLock (but we could use another lock) - Tokenizer mTokens; - DefaultKeyedVector<ClientID, Client*> mClientsMap; - DefaultKeyedVector<SurfaceID, LayerBaseClient*> mLayerMap; - GraphicPlane mGraphicPlanes[1]; - SortedVector<LayerBase*> mRemovedLayers; - Vector<Client*> mDisconnectedClients; - - // constant members (no synchronization needed for access) - sp<MemoryDealer> mServerHeap; - sp<IMemory> mServerCblkMemory; - surface_flinger_cblk_t* mServerCblk; - sp<SurfaceHeapManager> mSurfaceHeapManager; - sp<GPUHardwareInterface> mGPU; - GLuint mWormholeTexName; - sp<BootAnimation> mBootAnimation; - nsecs_t mBootTime; - - // Can only accessed from the main thread, these members - // don't need synchronization - Region mDirtyRegion; - Region mInvalidRegion; - Region mWormholeRegion; - Client* mLastScheduledBroadcast; - SortedVector<Client*> mScheduledBroadcasts; - bool mVisibleRegionsDirty; - bool mDeferReleaseConsole; - bool mFreezeDisplay; - int32_t mFreezeCount; - nsecs_t mFreezeDisplayTime; - friend class OrientationAnimation; - OrientationAnimation* mOrientationAnimation; - - // access protected by mDebugLock - mutable Mutex mDebugLock; - sp<CPUGauge> mCpuGauge; - - // don't use a lock for these, we don't care - int mDebugRegion; - int mDebugCpu; - int mDebugFps; - int mDebugBackground; - int mDebugNoBootAnimation; - - // these are thread safe - mutable Barrier mReadyToRunBarrier; - mutable SurfaceFlingerSynchro mSyncObject; - volatile int32_t mDeplayedTransactionPending; - - // atomic variables - enum { - eConsoleReleased = 1, - eConsoleAcquired = 2 - }; - volatile int32_t mConsoleSignals; - - // only written in the main thread, only read in other threads - volatile int32_t mSecureFrameBuffer; -}; - -// --------------------------------------------------------------------------- - -class FreezeLock : public LightRefBase<FreezeLock> { - SurfaceFlinger* mFlinger; -public: - FreezeLock(SurfaceFlinger* flinger) - : mFlinger(flinger) { - mFlinger->incFreezeCount(); - } - ~FreezeLock() { - mFlinger->decFreezeCount(); - } -}; - -// --------------------------------------------------------------------------- - -class BClient : public BnSurfaceFlingerClient -{ -public: - BClient(SurfaceFlinger *flinger, ClientID cid, - const sp<IMemory>& cblk); - ~BClient(); - - // ISurfaceFlingerClient interface - virtual void getControlBlocks(sp<IMemory>* ctrl) const; - - virtual sp<ISurface> createSurface( - surface_data_t* params, int pid, - DisplayID display, uint32_t w, uint32_t h,PixelFormat format, - uint32_t flags); - - virtual status_t destroySurface(SurfaceID surfaceId); - virtual status_t setState(int32_t count, const layer_state_t* states); - -private: - ClientID mId; - SurfaceFlinger* mFlinger; - sp<IMemory> mCblk; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_SURFACE_FLINGER_H diff --git a/libs/surfaceflinger/Tokenizer.cpp b/libs/surfaceflinger/Tokenizer.cpp deleted file mode 100644 index ef51d6a..0000000 --- a/libs/surfaceflinger/Tokenizer.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> - -#include "Tokenizer.h" - -// ---------------------------------------------------------------------------- - -namespace android { - -ANDROID_BASIC_TYPES_TRAITS(Tokenizer::run_t) - -Tokenizer::Tokenizer() -{ -} - -Tokenizer::Tokenizer(const Tokenizer& other) - : mRanges(other.mRanges) -{ -} - -Tokenizer::~Tokenizer() -{ -} - -uint32_t Tokenizer::acquire() -{ - if (!mRanges.size() || mRanges[0].first) { - _insertTokenAt(0,0); - return 0; - } - - // just extend the first run - const run_t& run = mRanges[0]; - uint32_t token = run.first + run.length; - _insertTokenAt(token, 1); - return token; -} - -bool Tokenizer::isAcquired(uint32_t token) const -{ - return (_indexOrderOf(token) >= 0); -} - -status_t Tokenizer::reserve(uint32_t token) -{ - size_t o; - const ssize_t i = _indexOrderOf(token, &o); - if (i >= 0) { - return BAD_VALUE; // this token is already taken - } - ssize_t err = _insertTokenAt(token, o); - return (err<0) ? err : status_t(NO_ERROR); -} - -status_t Tokenizer::release(uint32_t token) -{ - const ssize_t i = _indexOrderOf(token); - if (i >= 0) { - const run_t& run = mRanges[i]; - if ((token >= run.first) && (token < run.first+run.length)) { - // token in this range, we need to split - run_t& run = mRanges.editItemAt(i); - if ((token == run.first) || (token == run.first+run.length-1)) { - if (token == run.first) { - run.first += 1; - } - run.length -= 1; - if (run.length == 0) { - // XXX: should we systematically remove a run that's empty? - mRanges.removeItemsAt(i); - } - } else { - // split the run - run_t new_run; - new_run.first = token+1; - new_run.length = run.first+run.length - new_run.first; - run.length = token - run.first; - mRanges.insertAt(new_run, i+1); - } - return NO_ERROR; - } - } - return NAME_NOT_FOUND; -} - -ssize_t Tokenizer::_indexOrderOf(uint32_t token, size_t* order) const -{ - // binary search - ssize_t err = NAME_NOT_FOUND; - ssize_t l = 0; - ssize_t h = mRanges.size()-1; - ssize_t mid; - const run_t* a = mRanges.array(); - while (l <= h) { - mid = l + (h - l)/2; - const run_t* const curr = a + mid; - int c = 0; - if (token < curr->first) c = 1; - else if (token >= curr->first+curr->length) c = -1; - if (c == 0) { - err = l = mid; - break; - } else if (c < 0) { - l = mid + 1; - } else { - h = mid - 1; - } - } - if (order) *order = l; - return err; -} - -ssize_t Tokenizer::_insertTokenAt(uint32_t token, size_t index) -{ - const size_t c = mRanges.size(); - - if (index >= 1) { - // do we need to merge with the previous run? - run_t& p = mRanges.editItemAt(index-1); - if (p.first+p.length == token) { - p.length += 1; - if (index < c) { - const run_t& n = mRanges[index]; - if (token+1 == n.first) { - p.length += n.length; - mRanges.removeItemsAt(index); - } - } - return index; - } - } - - if (index < c) { - // do we need to merge with the next run? - run_t& n = mRanges.editItemAt(index); - if (token+1 == n.first) { - n.first -= 1; - n.length += 1; - return index; - } - } - - return mRanges.insertAt(run_t(token,1), index); -} - -void Tokenizer::dump() const -{ - const run_t* ranges = mRanges.array(); - const size_t c = mRanges.size(); - printf("Tokenizer (%p, size = %lu)\n", this, c); - for (size_t i=0 ; i<c ; i++) { - printf("%lu: (%u, %u)\n", i, ranges[i].first, ranges[i].length); - } -} - -}; // namespace android - diff --git a/libs/surfaceflinger/Tokenizer.h b/libs/surfaceflinger/Tokenizer.h deleted file mode 100644 index 6b3057d..0000000 --- a/libs/surfaceflinger/Tokenizer.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_TOKENIZER_H -#define ANDROID_TOKENIZER_H - -#include <utils/Vector.h> -#include <utils/Errors.h> - -// ---------------------------------------------------------------------------- - -namespace android { - -class Tokenizer -{ -public: - Tokenizer(); - Tokenizer(const Tokenizer& other); - ~Tokenizer(); - - uint32_t acquire(); - status_t reserve(uint32_t token); - status_t release(uint32_t token); - bool isAcquired(uint32_t token) const; - - void dump() const; - - struct run_t { - run_t() {}; - run_t(uint32_t f, uint32_t l) : first(f), length(l) {} - uint32_t first; - uint32_t length; - }; -private: - ssize_t _indexOrderOf(uint32_t token, size_t* order=0) const; - ssize_t _insertTokenAt(uint32_t token, size_t index); - Vector<run_t> mRanges; -}; - -}; // namespace android - -// ---------------------------------------------------------------------------- - -#endif // ANDROID_TOKENIZER_H diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp deleted file mode 100644 index bec7a64..0000000 --- a/libs/surfaceflinger/Transform.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <ui/Region.h> - -#include <private/pixelflinger/ggl_fixed.h> - -#include "Transform.h" - -// --------------------------------------------------------------------------- - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// --------------------------------------------------------------------------- - -namespace android { - -// --------------------------------------------------------------------------- - -Transform::Transform() - : mType(0) -{ - mTransform.reset(); -} - -Transform::Transform(const Transform& other) - : mTransform(other.mTransform), mType(other.mType) -{ -} - -Transform::~Transform() { -} - -Transform Transform::operator * (const Transform& rhs) const -{ - if (LIKELY(mType == 0)) - return rhs; - - Transform r(*this); - r.mTransform.preConcat(rhs.mTransform); - r.mType |= rhs.mType; - return r; -} - -float Transform::operator [] (int i) const -{ - float r = 0; - switch(i) { - case 0: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleX] ); break; - case 1: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewX] ); break; - case 2: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewY] ); break; - case 3: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleY] ); break; - } - return r; -} - -uint8_t Transform::type() const -{ - if (UNLIKELY(mType & 0x80000000)) { - mType = mTransform.getType(); - } - return uint8_t(mType & 0xFF); -} - -bool Transform::transformed() const { - return type() > SkMatrix::kTranslate_Mask; -} - -int Transform::tx() const { - return SkScalarRound( mTransform[SkMatrix::kMTransX] ); -} - -int Transform::ty() const { - return SkScalarRound( mTransform[SkMatrix::kMTransY] ); -} - -void Transform::reset() { - mTransform.reset(); - mType = 0; -} - -void Transform::set( float xx, float xy, - float yx, float yy) -{ - mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(xx)); - mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(xy)); - mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(yx)); - mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(yy)); - mType |= 0x80000000; -} - -void Transform::set(int tx, int ty) -{ - if (tx | ty) { - mTransform.set(SkMatrix::kMTransX, SkIntToScalar(tx)); - mTransform.set(SkMatrix::kMTransY, SkIntToScalar(ty)); - mType |= SkMatrix::kTranslate_Mask; - } else { - mTransform.set(SkMatrix::kMTransX, 0); - mTransform.set(SkMatrix::kMTransY, 0); - mType &= ~SkMatrix::kTranslate_Mask; - } -} - -void Transform::transform(GLfixed* point, int x, int y) const -{ - SkPoint s; - mTransform.mapXY(SkIntToScalar(x), SkIntToScalar(y), &s); - point[0] = SkScalarToFixed(s.fX); - point[1] = SkScalarToFixed(s.fY); -} - -Rect Transform::makeBounds(int w, int h) const -{ - Rect r; - SkRect d, s; - s.set(0, 0, SkIntToScalar(w), SkIntToScalar(h)); - mTransform.mapRect(&d, s); - r.left = SkScalarRound( d.fLeft ); - r.top = SkScalarRound( d.fTop ); - r.right = SkScalarRound( d.fRight ); - r.bottom = SkScalarRound( d.fBottom ); - return r; -} - -Rect Transform::transform(const Rect& bounds) const -{ - Rect r; - SkRect d, s; - s.set( SkIntToScalar( bounds.left ), - SkIntToScalar( bounds.top ), - SkIntToScalar( bounds.right ), - SkIntToScalar( bounds.bottom )); - mTransform.mapRect(&d, s); - r.left = SkScalarRound( d.fLeft ); - r.top = SkScalarRound( d.fTop ); - r.right = SkScalarRound( d.fRight ); - r.bottom = SkScalarRound( d.fBottom ); - return r; -} - -Region Transform::transform(const Region& reg) const -{ - Region out; - if (UNLIKELY(transformed())) { - if (LIKELY(preserveRects())) { - Rect r; - Region::iterator iterator(reg); - while (iterator.iterate(&r)) { - out.orSelf(transform(r)); - } - } else { - out.set(transform(reg.bounds())); - } - } else { - out = reg.translate(tx(), ty()); - } - return out; -} - -int32_t Transform::getOrientation() const -{ - uint32_t flags = 0; - if (UNLIKELY(transformed())) { - SkScalar a = mTransform[SkMatrix::kMScaleX]; - SkScalar b = mTransform[SkMatrix::kMSkewX]; - SkScalar c = mTransform[SkMatrix::kMSkewY]; - SkScalar d = mTransform[SkMatrix::kMScaleY]; - if (b==0 && c==0 && a && d) { - if (a<0) flags |= FLIP_H; - if (d<0) flags |= FLIP_V; - } else if (b && c && a==0 && d==0) { - flags |= ROT_90; - if (b>0) flags |= FLIP_H; - if (c<0) flags |= FLIP_V; - } else { - flags = 0x80000000; - } - } - return flags; -} - -bool Transform::preserveRects() const -{ - return mTransform.rectStaysRect(); -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h deleted file mode 100644 index 0b4835e..0000000 --- a/libs/surfaceflinger/Transform.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_TRANSFORM_H -#define ANDROID_TRANSFORM_H - -#include <stdint.h> -#include <sys/types.h> - -#include <ui/Point.h> -#include <ui/Rect.h> - -#include <GLES/gl.h> - -#include <core/SkMatrix.h> - -namespace android { - -class Region; - -// --------------------------------------------------------------------------- - -class Transform -{ -public: - Transform(); - Transform(const Transform& other); - ~Transform(); - - enum orientation_flags { - ROT_0 = 0x00000000, - FLIP_H = 0x00000001, - FLIP_V = 0x00000002, - ROT_90 = 0x00000004, - ROT_180 = FLIP_H|FLIP_V, - ROT_270 = ROT_180|ROT_90, - ROT_INVALID = 0x80000000 - }; - - bool transformed() const; - int32_t getOrientation() const; - bool preserveRects() const; - - int tx() const; - int ty() const; - - void reset(); - void set(float xx, float xy, float yx, float yy); - void set(int tx, int ty); - - Rect makeBounds(int w, int h) const; - void transform(GLfixed* point, int x, int y) const; - Region transform(const Region& reg) const; - Rect transform(const Rect& bounds) const; - - Transform operator * (const Transform& rhs) const; - float operator [] (int i) const; - - inline uint32_t getType() const { return type(); } - - inline Transform(bool) : mType(0xFF) { }; - -private: - uint8_t type() const; - -private: - SkMatrix mTransform; - mutable uint32_t mType; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif /* ANDROID_TRANSFORM_H */ diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp deleted file mode 100644 index 0ccd71f..0000000 --- a/libs/surfaceflinger/VRamHeap.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <math.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <cutils/log.h> -#include <cutils/properties.h> - -#include <utils/MemoryDealer.h> -#include <utils/MemoryBase.h> -#include <utils/MemoryHeapPmem.h> -#include <utils/MemoryHeapBase.h> - -#include "GPUHardware/GPUHardware.h" -#include "SurfaceFlinger.h" -#include "VRamHeap.h" - -#if HAVE_ANDROID_OS -#include <linux/android_pmem.h> -#endif - - -namespace android { - -// --------------------------------------------------------------------------- - -/* - * Amount of memory we reserve for surface, per client in PMEM - * (PMEM is used for 2D acceleration) - * 8 MB of address space per client should be enough. - */ -static const int PMEM_SIZE = int(8 * 1024 * 1024); - -int SurfaceHeapManager::global_pmem_heap = 0; - -// --------------------------------------------------------------------------- - -SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, - size_t clientHeapSize) - : mFlinger(flinger), mClientHeapSize(clientHeapSize) -{ - SurfaceHeapManager::global_pmem_heap = 1; -} - -SurfaceHeapManager::~SurfaceHeapManager() -{ -} - -void SurfaceHeapManager::onFirstRef() -{ - if (global_pmem_heap) { - const char* device = "/dev/pmem"; - mPMemHeap = new PMemHeap(device, PMEM_SIZE); - if (mPMemHeap->base() == MAP_FAILED) { - mPMemHeap.clear(); - global_pmem_heap = 0; - } - } -} - -sp<MemoryDealer> SurfaceHeapManager::createHeap( - uint32_t flags, - pid_t client_pid, - const sp<MemoryDealer>& defaultAllocator) -{ - sp<MemoryDealer> dealer; - - if (flags & ISurfaceComposer::eGPU) { - // don't grant GPU memory if GPU is disabled - char value[PROPERTY_VALUE_MAX]; - property_get("debug.egl.hw", value, "1"); - if (atoi(value) == 0) { - flags &= ~ISurfaceComposer::eGPU; - } - } - - if (flags & ISurfaceComposer::eGPU) { - // FIXME: this is msm7201A specific, where gpu surfaces may not be secure - if (!(flags & ISurfaceComposer::eSecure)) { - // if GPU doesn't work, we try eHardware - flags |= ISurfaceComposer::eHardware; - // asked for GPU memory, try that first - dealer = mFlinger->getGPU()->request(client_pid); - } - } - - if (dealer == NULL) { - if (defaultAllocator != NULL) - // if a default allocator is given, use that - dealer = defaultAllocator; - } - - if (dealer == NULL) { - // always try h/w accelerated memory first - if (global_pmem_heap) { - const sp<PMemHeap>& heap(mPMemHeap); - if (dealer == NULL && heap != NULL) { - dealer = new MemoryDealer( - heap->createClientHeap(), - heap->getAllocator()); - } - } - } - - if (dealer == NULL) { - // return the ashmem allocator (software rendering) - dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap"); - } - return dealer; -} - -sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const -{ - Mutex::Autolock _l(mLock); - sp<SimpleBestFitAllocator> allocator; - - // this is only used for debugging - switch (type) { - case NATIVE_MEMORY_TYPE_PMEM: - if (mPMemHeap != 0) { - allocator = mPMemHeap->getAllocator(); - } - break; - } - return allocator; -} - -// --------------------------------------------------------------------------- - -PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved) - : MemoryHeapBase(device, size) -{ - //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); - if (base() != MAP_FAILED) { - //LOGD("%s, %u bytes", device, virtualSize()); - if (reserved == 0) - reserved = virtualSize(); - mAllocator = new SimpleBestFitAllocator(reserved); - } -} - -PMemHeap::~PMemHeap() { - //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); -} - -sp<MemoryHeapPmem> PMemHeap::createClientHeap() { - sp<MemoryHeapBase> parentHeap(this); - return new MemoryHeapPmem(parentHeap); -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/surfaceflinger/VRamHeap.h b/libs/surfaceflinger/VRamHeap.h deleted file mode 100644 index 9140167..0000000 --- a/libs/surfaceflinger/VRamHeap.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_VRAM_HEAP_H -#define ANDROID_VRAM_HEAP_H - -#include <stdint.h> -#include <sys/types.h> -#include <utils/MemoryDealer.h> - -namespace android { - -// --------------------------------------------------------------------------- - -class PMemHeap; -class MemoryHeapPmem; -class SurfaceFlinger; - -// --------------------------------------------------------------------------- - -class SurfaceHeapManager : public RefBase -{ -public: - SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize); - virtual ~SurfaceHeapManager(); - virtual void onFirstRef(); - /* use ISurfaceComposer flags eGPU|eHArdware|eSecure */ - sp<MemoryDealer> createHeap(uint32_t flags=0, pid_t client_pid = 0, - const sp<MemoryDealer>& defaultAllocator = 0); - - // used for debugging only... - sp<SimpleBestFitAllocator> getAllocator(int type) const; - -private: - sp<PMemHeap> getHeap(int type) const; - - sp<SurfaceFlinger> mFlinger; - mutable Mutex mLock; - size_t mClientHeapSize; - sp<PMemHeap> mPMemHeap; - static int global_pmem_heap; -}; - -// --------------------------------------------------------------------------- - -class PMemHeap : public MemoryHeapBase -{ -public: - PMemHeap(const char* const vram, - size_t size=0, size_t reserved=0); - virtual ~PMemHeap(); - - virtual const sp<SimpleBestFitAllocator>& getAllocator() const { - return mAllocator; - } - virtual sp<MemoryHeapPmem> createClientHeap(); - -private: - sp<SimpleBestFitAllocator> mAllocator; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_VRAM_HEAP_H diff --git a/libs/surfaceflinger/clz.cpp b/libs/surfaceflinger/clz.cpp deleted file mode 100644 index 2456b86..0000000 --- a/libs/surfaceflinger/clz.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "clz.h" - -namespace android { - -int clz_impl(int32_t x) -{ -#if defined(__arm__) && !defined(__thumb__) - return __builtin_clz(x); -#else - if (!x) return 32; - int e = 31; - if (x&0xFFFF0000) { e -=16; x >>=16; } - if (x&0x0000FF00) { e -= 8; x >>= 8; } - if (x&0x000000F0) { e -= 4; x >>= 4; } - if (x&0x0000000C) { e -= 2; x >>= 2; } - if (x&0x00000002) { e -= 1; } - return e; -#endif -} - -}; // namespace android diff --git a/libs/surfaceflinger/clz.h b/libs/surfaceflinger/clz.h deleted file mode 100644 index 0ddf986..0000000 --- a/libs/surfaceflinger/clz.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_SURFACE_FLINGER_CLZ_H - -#include <stdint.h> - -namespace android { - -int clz_impl(int32_t x); - -int inline clz(int32_t x) -{ -#if defined(__arm__) && !defined(__thumb__) - return __builtin_clz(x); -#else - return clz_impl(x); -#endif -} - - -}; // namespace android - -#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */ diff --git a/libs/surfaceflinger/tests/Android.mk b/libs/surfaceflinger/tests/Android.mk deleted file mode 100644 index 5053e7d..0000000 --- a/libs/surfaceflinger/tests/Android.mk +++ /dev/null @@ -1 +0,0 @@ -include $(call all-subdir-makefiles) diff --git a/libs/surfaceflinger/tests/overlays/Android.mk b/libs/surfaceflinger/tests/overlays/Android.mk deleted file mode 100644 index dc47e45..0000000 --- a/libs/surfaceflinger/tests/overlays/Android.mk +++ /dev/null @@ -1,16 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - overlays.cpp - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libui - -LOCAL_MODULE:= test-overlays - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_EXECUTABLE) diff --git a/libs/surfaceflinger/tests/overlays/overlays.cpp b/libs/surfaceflinger/tests/overlays/overlays.cpp deleted file mode 100644 index f3c046f..0000000 --- a/libs/surfaceflinger/tests/overlays/overlays.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include <utils/IPCThreadState.h> -#include <utils/ProcessState.h> -#include <utils/IServiceManager.h> -#include <utils/Log.h> - -#include <ui/Surface.h> -#include <ui/ISurface.h> -#include <ui/Overlay.h> -#include <ui/SurfaceComposerClient.h> - -using namespace android; - -namespace android { -class Test { -public: - static const sp<ISurface>& getISurface(const sp<Surface>& s) { - return s->getISurface(); - } -}; -}; - -int main(int argc, char** argv) -{ - // set up the thread-pool - sp<ProcessState> proc(ProcessState::self()); - ProcessState::self()->startThreadPool(); - - // create a client to surfaceflinger - sp<SurfaceComposerClient> client = new SurfaceComposerClient(); - - // create pushbuffer surface - sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240, - PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers); - - // get to the isurface - sp<ISurface> isurface = Test::getISurface(surface); - printf("isurface = %p\n", isurface.get()); - - // now request an overlay - sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565); - sp<Overlay> overlay = new Overlay(ref); - - - /* - * here we can use the overlay API - */ - - overlay_buffer_t buffer; - overlay->dequeueBuffer(&buffer); - printf("buffer = %p\n", buffer); - - void* address = overlay->getBufferAddress(buffer); - printf("address = %p\n", address); - - overlay->queueBuffer(buffer); - - return 0; -} diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk deleted file mode 100644 index f944357..0000000 --- a/libs/ui/Android.mk +++ /dev/null @@ -1,41 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - Camera.cpp \ - CameraParameters.cpp \ - EGLDisplaySurface.cpp \ - EGLNativeWindowSurface.cpp \ - EventHub.cpp \ - EventRecurrence.cpp \ - KeyLayoutMap.cpp \ - KeyCharacterMap.cpp \ - ICamera.cpp \ - ICameraClient.cpp \ - ICameraService.cpp \ - IOverlay.cpp \ - ISurfaceComposer.cpp \ - ISurface.cpp \ - ISurfaceFlingerClient.cpp \ - LayerState.cpp \ - Overlay.cpp \ - PixelFormat.cpp \ - Point.cpp \ - Rect.cpp \ - Region.cpp \ - Surface.cpp \ - SurfaceComposerClient.cpp \ - SurfaceFlingerSynchro.cpp \ - Time.cpp - -LOCAL_SHARED_LIBRARIES := \ - libcorecg \ - libcutils \ - libutils \ - libpixelflinger \ - libhardware \ - libhardware_legacy - -LOCAL_MODULE:= libui - -include $(BUILD_SHARED_LIBRARY) diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp deleted file mode 100644 index 6c60b85..0000000 --- a/libs/ui/Camera.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* -** -** Copyright (C) 2008, The Android Open Source Project -** Copyright (C) 2008 HTC Inc. -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "Camera" -#include <utils/Log.h> -#include <utils/IServiceManager.h> -#include <utils/threads.h> -#include <utils/IMemory.h> -#include <ui/Surface.h> -#include <ui/Camera.h> -#include <ui/ICameraService.h> - -namespace android { - -// client singleton for camera service binder interface -Mutex Camera::mLock; -sp<ICameraService> Camera::mCameraService; -sp<Camera::DeathNotifier> Camera::mDeathNotifier; - -// establish binder interface to camera service -const sp<ICameraService>& Camera::getCameraService() -{ - Mutex::Autolock _l(mLock); - if (mCameraService.get() == 0) { - sp<IServiceManager> sm = defaultServiceManager(); - sp<IBinder> binder; - do { - binder = sm->getService(String16("media.camera")); - if (binder != 0) - break; - LOGW("CameraService not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - if (mDeathNotifier == NULL) { - mDeathNotifier = new DeathNotifier(); - } - binder->linkToDeath(mDeathNotifier); - mCameraService = interface_cast<ICameraService>(binder); - } - LOGE_IF(mCameraService==0, "no CameraService!?"); - return mCameraService; -} - -// --------------------------------------------------------------------------- - -Camera::Camera() -{ - init(); -} - -Camera::Camera(const sp<ICamera>& camera) -{ - init(); - // connect this client to existing camera remote - if (camera->connect(this) == NO_ERROR) { - mStatus = NO_ERROR; - mCamera = camera; - camera->asBinder()->linkToDeath(this); - } -} - -void Camera::init() -{ - mStatus = UNKNOWN_ERROR; - mShutterCallback = 0; - mShutterCallbackCookie = 0; - mRawCallback = 0; - mRawCallbackCookie = 0; - mJpegCallback = 0; - mJpegCallbackCookie = 0; - mPreviewCallback = 0; - mPreviewCallbackCookie = 0; - mRecordingCallback = 0; - mRecordingCallbackCookie = 0; - mErrorCallback = 0; - mErrorCallbackCookie = 0; - mAutoFocusCallback = 0; - mAutoFocusCallbackCookie = 0; -} - -Camera::~Camera() -{ - disconnect(); -} - -sp<Camera> Camera::connect() -{ - LOGV("connect"); - sp<Camera> c = new Camera(); - const sp<ICameraService>& cs = getCameraService(); - if (cs != 0) { - c->mCamera = cs->connect(c); - } - if (c->mCamera != 0) { - c->mCamera->asBinder()->linkToDeath(c); - c->mStatus = NO_ERROR; - } - return c; -} - -void Camera::disconnect() -{ - LOGV("disconnect"); - if (mCamera != 0) { - mErrorCallback = 0; - mCamera->disconnect(); - mCamera = 0; - } -} - -status_t Camera::reconnect() -{ - LOGV("reconnect"); - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->connect(this); -} - -sp<ICamera> Camera::remote() -{ - return mCamera; -} - -status_t Camera::lock() -{ - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->lock(); -} - -status_t Camera::unlock() -{ - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->unlock(); -} - -// pass the buffered ISurface to the camera service -status_t Camera::setPreviewDisplay(const sp<Surface>& surface) -{ - LOGV("setPreviewDisplay"); - if (surface == 0) { - LOGE("app passed NULL surface"); - return NO_INIT; - } - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->setPreviewDisplay(surface->getISurface()); -} - -status_t Camera::setPreviewDisplay(const sp<ISurface>& surface) -{ - LOGV("setPreviewDisplay"); - if (surface == 0) { - LOGE("app passed NULL surface"); - return NO_INIT; - } - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->setPreviewDisplay(surface); -} - - -// start preview mode, must call setPreviewDisplay first -status_t Camera::startPreview() -{ - LOGV("startPreview"); - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->startPreview(); -} - -// start recording mode, must call setPreviewDisplay first -status_t Camera::startRecording() -{ - LOGV("startRecording"); - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->startRecording(); -} - -// stop preview mode -void Camera::stopPreview() -{ - LOGV("stopPreview"); - sp <ICamera> c = mCamera; - if (c == 0) return; - c->stopPreview(); -} - -// stop recording mode -void Camera::stopRecording() -{ - LOGV("stopRecording"); - sp <ICamera> c = mCamera; - if (c == 0) return; - c->stopRecording(); -} - -// release a recording frame -void Camera::releaseRecordingFrame(const sp<IMemory>& mem) -{ - LOGV("releaseRecordingFrame"); - sp <ICamera> c = mCamera; - if (c == 0) return; - c->releaseRecordingFrame(mem); -} - -// get preview state -bool Camera::previewEnabled() -{ - LOGV("previewEnabled"); - sp <ICamera> c = mCamera; - if (c == 0) return false; - return c->previewEnabled(); -} - -// get recording state -bool Camera::recordingEnabled() -{ - LOGV("recordingEnabled"); - sp <ICamera> c = mCamera; - if (c == 0) return false; - return c->recordingEnabled(); -} - -status_t Camera::autoFocus() -{ - LOGV("autoFocus"); - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->autoFocus(); -} - -// take a picture -status_t Camera::takePicture() -{ - LOGV("takePicture"); - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->takePicture(); -} - -// set preview/capture parameters - key/value pairs -status_t Camera::setParameters(const String8& params) -{ - LOGV("setParameters"); - sp <ICamera> c = mCamera; - if (c == 0) return NO_INIT; - return c->setParameters(params); -} - -// get preview/capture parameters - key/value pairs -String8 Camera::getParameters() const -{ - LOGV("getParameters"); - String8 params; - sp <ICamera> c = mCamera; - if (c != 0) params = mCamera->getParameters(); - return params; -} - -void Camera::setAutoFocusCallback(autofocus_callback cb, void *cookie) -{ - LOGV("setAutoFocusCallback"); - mAutoFocusCallback = cb; - mAutoFocusCallbackCookie = cookie; -} - -void Camera::setShutterCallback(shutter_callback cb, void *cookie) -{ - LOGV("setShutterCallback"); - mShutterCallback = cb; - mShutterCallbackCookie = cookie; -} - -void Camera::setRawCallback(frame_callback cb, void *cookie) -{ - LOGV("setRawCallback"); - mRawCallback = cb; - mRawCallbackCookie = cookie; -} - -void Camera::setJpegCallback(frame_callback cb, void *cookie) -{ - LOGV("setJpegCallback"); - mJpegCallback = cb; - mJpegCallbackCookie = cookie; -} - -void Camera::setPreviewCallback(frame_callback cb, void *cookie, int flag) -{ - LOGV("setPreviewCallback"); - mPreviewCallback = cb; - mPreviewCallbackCookie = cookie; - sp <ICamera> c = mCamera; - if (c == 0) return; - mCamera->setPreviewCallbackFlag(flag); -} - -void Camera::setRecordingCallback(frame_callback cb, void *cookie) -{ - LOGV("setRecordingCallback"); - mRecordingCallback = cb; - mRecordingCallbackCookie = cookie; -} - -void Camera::setErrorCallback(error_callback cb, void *cookie) -{ - LOGV("setErrorCallback"); - mErrorCallback = cb; - mErrorCallbackCookie = cookie; -} - -void Camera::autoFocusCallback(bool focused) -{ - LOGV("autoFocusCallback"); - if (mAutoFocusCallback) { - mAutoFocusCallback(focused, mAutoFocusCallbackCookie); - } -} - -void Camera::shutterCallback() -{ - LOGV("shutterCallback"); - if (mShutterCallback) { - mShutterCallback(mShutterCallbackCookie); - } -} - -void Camera::rawCallback(const sp<IMemory>& picture) -{ - LOGV("rawCallback"); - if (mRawCallback) { - mRawCallback(picture, mRawCallbackCookie); - } -} - -// callback from camera service when image is ready -void Camera::jpegCallback(const sp<IMemory>& picture) -{ - LOGV("jpegCallback"); - if (mJpegCallback) { - mJpegCallback(picture, mJpegCallbackCookie); - } -} - -// callback from camera service when preview frame is ready -void Camera::previewCallback(const sp<IMemory>& frame) -{ - LOGV("frameCallback"); - if (mPreviewCallback) { - mPreviewCallback(frame, mPreviewCallbackCookie); - } -} - -// callback from camera service when a recording frame is ready -void Camera::recordingCallback(const sp<IMemory>& frame) -{ - LOGV("recordingCallback"); - if (mRecordingCallback) { - mRecordingCallback(frame, mRecordingCallbackCookie); - } -} - -// callback from camera service when an error occurs in preview or takePicture -void Camera::errorCallback(status_t error) -{ - LOGV("errorCallback"); - if (mErrorCallback) { - mErrorCallback(error, mErrorCallbackCookie); - } -} - -void Camera::binderDied(const wp<IBinder>& who) { - LOGW("ICamera died"); - if (mErrorCallback) { - mErrorCallback(DEAD_OBJECT, mErrorCallbackCookie); - } -} - -void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) { - LOGV("binderDied"); - Mutex::Autolock _l(Camera::mLock); - Camera::mCameraService.clear(); - LOGW("Camera server died!"); -} - -}; // namespace android - diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp deleted file mode 100644 index 6c25836..0000000 --- a/libs/ui/CameraParameters.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* -** -** Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_TAG "CameraParams" -#include <utils/Log.h> - -#include <string.h> -#include <stdlib.h> -#include <ui/CameraParameters.h> - -namespace android { - -static const char* portrait = "portrait"; -static const char* landscape = "landscape"; - -CameraParameters::CameraParameters() - : mMap() -{ -} - -CameraParameters::~CameraParameters() -{ -} - -String8 CameraParameters::flatten() const -{ - String8 flattened(""); - size_t size = mMap.size(); - - for (size_t i = 0; i < size; i++) { - String8 k, v; - k = mMap.keyAt(i); - v = mMap.valueAt(i); - - flattened += k; - flattened += "="; - flattened += v; - if (i != size-1) - flattened += ";"; - } - - return flattened; -} - -void CameraParameters::unflatten(const String8 ¶ms) -{ - const char *a = params.string(); - const char *b; - - mMap.clear(); - - for (;;) { - // Find the bounds of the key name. - b = strchr(a, '='); - if (b == 0) - break; - - // Create the key string. - String8 k(a, (size_t)(b-a)); - - // Find the value. - a = b+1; - b = strchr(a, ';'); - if (b == 0) { - // If there's no semicolon, this is the last item. - String8 v(a); - mMap.add(k, v); - break; - } - - String8 v(a, (size_t)(b-a)); - mMap.add(k, v); - a = b+1; - } -} - - -void CameraParameters::set(const char *key, const char *value) -{ - // XXX i think i can do this with strspn() - if (strchr(key, '=') || strchr(key, ';')) { - //XXX LOGE("Key \"%s\"contains invalid character (= or ;)", key); - return; - } - - if (strchr(value, '=') || strchr(key, ';')) { - //XXX LOGE("Value \"%s\"contains invalid character (= or ;)", value); - return; - } - - mMap.replaceValueFor(String8(key), String8(value)); -} - -void CameraParameters::set(const char *key, int value) -{ - char str[16]; - sprintf(str, "%d", value); - set(key, str); -} - -const char *CameraParameters::get(const char *key) const -{ - String8 v = mMap.valueFor(String8(key)); - if (v.length() == 0) - return 0; - return v.string(); -} - -int CameraParameters::getInt(const char *key) const -{ - const char *v = get(key); - if (v == 0) - return -1; - return strtol(v, 0, 0); -} - -static int parse_size(const char *str, int &width, int &height) -{ - // Find the width. - char *end; - int w = (int)strtol(str, &end, 10); - // If an 'x' does not immediately follow, give up. - if (*end != 'x') - return -1; - - // Find the height, immediately after the 'x'. - int h = (int)strtol(end+1, 0, 10); - - width = w; - height = h; - - return 0; -} - -void CameraParameters::setPreviewSize(int width, int height) -{ - char str[32]; - sprintf(str, "%dx%d", width, height); - set("preview-size", str); -} - -void CameraParameters::getPreviewSize(int *width, int *height) const -{ - *width = -1; - *height = -1; - - // Get the current string, if it doesn't exist, leave the -1x-1 - const char *p = get("preview-size"); - if (p == 0) - return; - - int w, h; - if (parse_size(p, w, h) == 0) { - *width = w; - *height = h; - } -} - -void CameraParameters::setPreviewFrameRate(int fps) -{ - set("preview-frame-rate", fps); -} - -int CameraParameters::getPreviewFrameRate() const -{ - return getInt("preview-frame-rate"); -} - -void CameraParameters::setPreviewFormat(const char *format) -{ - set("preview-format", format); -} - -int CameraParameters::getOrientation() const -{ - const char* orientation = get("orientation"); - if (orientation && !strcmp(orientation, portrait)) - return CAMERA_ORIENTATION_PORTRAIT; - return CAMERA_ORIENTATION_LANDSCAPE; -} - -void CameraParameters::setOrientation(int orientation) -{ - if (orientation == CAMERA_ORIENTATION_PORTRAIT) { - set("preview-format", portrait); - } else { - set("preview-format", landscape); - } -} - -const char *CameraParameters::getPreviewFormat() const -{ - return get("preview-format"); -} - -void CameraParameters::setPictureSize(int width, int height) -{ - char str[32]; - sprintf(str, "%dx%d", width, height); - set("picture-size", str); -} - -void CameraParameters::getPictureSize(int *width, int *height) const -{ - *width = -1; - *height = -1; - - // Get the current string, if it doesn't exist, leave the -1x-1 - const char *p = get("picture-size"); - if (p == 0) - return; - - int w, h; - if (parse_size(p, w, h) == 0) { - *width = w; - *height = h; - } -} - -void CameraParameters::setPictureFormat(const char *format) -{ - set("picture-format", format); -} - -const char *CameraParameters::getPictureFormat() const -{ - return get("picture-format"); -} - -void CameraParameters::dump() const -{ - LOGD("dump: mMap.size = %d", mMap.size()); - for (size_t i = 0; i < mMap.size(); i++) { - String8 k, v; - k = mMap.keyAt(i); - v = mMap.valueAt(i); - LOGD("%s: %s\n", k.string(), v.string()); - } -} - -status_t CameraParameters::dump(int fd, const Vector<String16>& args) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, 255, "CameraParameters::dump: mMap.size = %d\n", mMap.size()); - result.append(buffer); - for (size_t i = 0; i < mMap.size(); i++) { - String8 k, v; - k = mMap.keyAt(i); - v = mMap.valueAt(i); - snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string()); - result.append(buffer); - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -}; // namespace android diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp deleted file mode 100644 index d06c98b..0000000 --- a/libs/ui/EGLDisplaySurface.cpp +++ /dev/null @@ -1,519 +0,0 @@ -/* - ** - ** Copyright 2007 The Android Open Source Project - ** - ** Licensed under the Apache License Version 2.0(the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing software - ** distributed under the License is distributed on an "AS IS" BASIS - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -#define LOG_TAG "EGLDisplaySurface" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/mman.h> - -#include <cutils/log.h> -#include <cutils/atomic.h> -#include <cutils/properties.h> - -#include <hardware/copybit.h> - -#include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> -#include <ui/Rect.h> -#include <ui/Region.h> -#include <ui/EGLDisplaySurface.h> - -#if HAVE_ANDROID_OS -#include <linux/msm_mdp.h> -#endif - -#include <EGL/egl.h> - -#include <pixelflinger/format.h> - - -// ---------------------------------------------------------------------------- - -egl_native_window_t* android_createDisplaySurface() -{ - egl_native_window_t* s = new android::EGLDisplaySurface(); - s->memory_type = NATIVE_MEMORY_TYPE_GPU; - return s; -} - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -EGLDisplaySurface::EGLDisplaySurface() - : EGLNativeSurface<EGLDisplaySurface>() -{ - egl_native_window_t::version = sizeof(egl_native_window_t); - egl_native_window_t::ident = 0; - egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef; - egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef; - egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers; - egl_native_window_t::connect = 0; - egl_native_window_t::disconnect = 0; - - mFb[0].data = 0; - mFb[1].data = 0; - mBlitEngine = 0; - egl_native_window_t::fd = mapFrameBuffer(); - if (egl_native_window_t::fd >= 0) { - - hw_module_t const* module; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } - - const float in2mm = 25.4f; - float refreshRate = 1000000000000000LLU / ( - float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres ) - * ( mInfo.left_margin + mInfo.right_margin + mInfo.xres ) - * mInfo.pixclock); - - const GGLSurface& buffer = mFb[1 - mIndex]; - egl_native_window_t::width = buffer.width; - egl_native_window_t::height = buffer.height; - egl_native_window_t::stride = buffer.stride; - egl_native_window_t::format = buffer.format; - egl_native_window_t::base = intptr_t(mFb[0].data); - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - egl_native_window_t::flags = 0; - egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width; - egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height; - egl_native_window_t::fps = refreshRate; - egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB; - // no error, set the magic word - egl_native_window_t::magic = 0x600913; - } - mSwapCount = -1; - mPageFlipCount = 0; -} - -EGLDisplaySurface::~EGLDisplaySurface() -{ - magic = 0; - copybit_close(mBlitEngine); - mBlitEngine = 0; - close(egl_native_window_t::fd); - munmap(mFb[0].data, mSize); - if (!(mFlags & PAGE_FLIP)) - free((void*)mFb[1].data); -} - -void EGLDisplaySurface::hook_incRef(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->incStrong(that); -} -void EGLDisplaySurface::hook_decRef(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->decStrong(that); -} -uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - return that->swapBuffers(); -} - -void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h) -{ - mInfo.reserved[0] = 0x54445055; // "UPDT"; - mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); - mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); -} - -uint32_t EGLDisplaySurface::swapBuffers() -{ -#define SHOW_FPS 0 -#if SHOW_FPS - nsecs_t now = systemTime(); - if (mSwapCount == -1) { - mTime = now; - mSwapCount = 0; - mSleep = 0; - } else { - nsecs_t d = now-mTime; - if (d >= seconds(1)) { - double fps = (mSwapCount * double(seconds(1))) / double(d); - LOGD("%f fps, sleep=%d / frame", - fps, (int)ns2us(mSleep / mSwapCount)); - mSwapCount = 0; - mTime = now; - mSleep = 0; - } else { - mSwapCount++; - } - } -#endif - /* If we can't do the page_flip, just copy the back buffer to the front */ - if (!(mFlags & PAGE_FLIP)) { - memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2); - return 0; - } - - // do the actual flip - mIndex = 1 - mIndex; - mInfo.activate = FB_ACTIVATE_VBL; - mInfo.yoffset = mIndex ? mInfo.yres : 0; - if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) { - LOGE("FBIOPUT_VSCREENINFO failed"); - return 0; - } - - /* - * this is a monstrous hack: Because the h/w accelerator is not able - * to render directly into the framebuffer, we need to copy its - * internal framebuffer out to the fb. - * oem[0] is used to access the fd of internal fb. - * All this is needed only in standalone mode, in SurfaceFlinger mode - * we control where the GPU renders. - * We do this only if we have copybit, since this hack is needed only - * with msm7k. - */ - if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0] && mBlitEngine) { - copybit_device_t *copybit = mBlitEngine; - copybit_rect_t sdrect = { 0, 0, - egl_native_window_t::width, egl_native_window_t::height }; - copybit_image_t dst = { - egl_native_window_t::width, - egl_native_window_t::height, - egl_native_window_t::format, - egl_native_window_t::offset, - (void*)egl_native_window_t::base, - egl_native_window_t::fd - }; - copybit_image_t src = { - egl_native_window_t::width, - egl_native_window_t::height, - egl_native_window_t::format, // XXX: use proper format - egl_native_window_t::offset, - (void*)egl_native_window_t::base, // XXX: use proper base - egl_native_window_t::oem[0] - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it); - } - - // update the address of the buffer to draw to next - const GGLSurface& buffer = mFb[1 - mIndex]; - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - -#if SHOW_FPS - mSleep += systemTime()-now; -#endif - - mPageFlipCount++; - - // We don't support screen-size changes for now - return 0; -} - -int32_t EGLDisplaySurface::getPageFlipCount() const -{ - return mPageFlipCount; -} - -void EGLDisplaySurface::copyFrontToBack(const Region& copyback) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t dst = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[1-mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(copyback); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - /* no extra copy needed since we copied back to front instead of - * flipping */ - if (!(mFlags & PAGE_FLIP)) { - return; - } - - Region::iterator iterator(copyback); - if (iterator) { - Rect r; - uint8_t* const screen_src = mFb[ mIndex].data; - uint8_t* const screen_dst = mFb[1-mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - while (iterator.iterate(&r)) { - ssize_t h = r.bottom - r.top; - if (h) { - size_t size = (r.right - r.left) * bpp; - size_t o = (r.left + egl_native_window_t::stride * r.top) * bpp; - uint8_t* s = screen_src + o; - uint8_t* d = screen_dst + o; - if (size == bpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += bpr; - s += bpr; - } while (--h > 0); - } - } - } - } -} - -void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - uint8_t* const screen_src = mFb[ mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - memcpy((char*)dst.base + dst.offset, screen_src, - bpr*egl_native_window_t::height); - } -} - -void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[1-mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - uint8_t* const screen_src = mFb[1-mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - memcpy((char*)dst.base + dst.offset, screen_src, - bpr*egl_native_window_t::height); - } -} - - -status_t EGLDisplaySurface::mapFrameBuffer() -{ - char const * const device_template[] = { - "/dev/graphics/fb%u", - "/dev/fb%u", - 0 }; - int fd = -1; - int i=0; - char name[64]; - while ((fd==-1) && device_template[i]) { - snprintf(name, 64, device_template[i], 0); - fd = open(name, O_RDWR, 0); - i++; - } - if (fd < 0) - return -errno; - - struct fb_fix_screeninfo finfo; - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) - return -errno; - - struct fb_var_screeninfo info; - if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - return -errno; - - info.reserved[0] = 0; - info.reserved[1] = 0; - info.reserved[2] = 0; - info.xoffset = 0; - info.yoffset = 0; - info.yres_virtual = info.yres * 2; - info.bits_per_pixel = 16; - /* Explicitly request 5/6/5 */ - info.red.offset = 11; - info.red.length = 5; - info.green.offset = 5; - info.green.length = 6; - info.blue.offset = 0; - info.blue.length = 5; - info.transp.offset = 0; - info.transp.length = 0; - info.activate = FB_ACTIVATE_NOW; - - uint32_t flags = PAGE_FLIP; - if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { - info.yres_virtual = info.yres; - flags &= ~PAGE_FLIP; - LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); - } - - if (info.yres_virtual < info.yres * 2) { - info.yres_virtual = info.yres; - flags &= ~PAGE_FLIP; - LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", - info.yres_virtual, info.yres*2); - } - - if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - return -errno; - - int refreshRate = 1000000000000000LLU / - ( - uint64_t( info.upper_margin + info.lower_margin + info.yres ) - * ( info.left_margin + info.right_margin + info.xres ) - * info.pixclock - ); - - if (refreshRate == 0) { - // bleagh, bad info from the driver - refreshRate = 60*1000; // 60 Hz - } - if (int(info.width) <= 0 || int(info.height) <= 0) { - // the driver doesn't return that information - // default to 160 dpi - info.width = ((info.xres * 25.4f)/160.0f + 0.5f); - info.height = ((info.yres * 25.4f)/160.0f + 0.5f); - } - - float xdpi = (info.xres * 25.4f) / info.width; - float ydpi = (info.yres * 25.4f) / info.height; - float fps = refreshRate / 1000.0f; - - LOGI( "using (fd=%d)\n" - "id = %s\n" - "xres = %d px\n" - "yres = %d px\n" - "xres_virtual = %d px\n" - "yres_virtual = %d px\n" - "bpp = %d\n" - "r = %2u:%u\n" - "g = %2u:%u\n" - "b = %2u:%u\n", - fd, - finfo.id, - info.xres, - info.yres, - info.xres_virtual, - info.yres_virtual, - info.bits_per_pixel, - info.red.offset, info.red.length, - info.green.offset, info.green.length, - info.blue.offset, info.blue.length - ); - - LOGI( "width = %d mm (%f dpi)\n" - "height = %d mm (%f dpi)\n" - "refresh rate = %.2f Hz\n", - info.width, xdpi, - info.height, ydpi, - fps - ); - - - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) - return -errno; - - if (finfo.smem_len <= 0) - return -errno; - - /* - * Open and map the display. - */ - - void* buffer = (uint16_t*) mmap( - 0, finfo.smem_len, - PROT_READ | PROT_WRITE, - MAP_SHARED, - fd, 0); - - if (buffer == MAP_FAILED) - return -errno; - - // at least for now, always clear the fb - memset(buffer, 0, finfo.smem_len); - - uint8_t* offscreen[2]; - offscreen[0] = (uint8_t*)buffer; - if (flags & PAGE_FLIP) { - offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres; - } else { - offscreen[1] = (uint8_t*)malloc(finfo.smem_len); - if (offscreen[1] == 0) { - munmap(buffer, finfo.smem_len); - return NO_MEMORY; - } - } - - mFlags = flags; - mInfo = info; - mFinfo = finfo; - mSize = finfo.smem_len; - mIndex = 0; - for (int i=0 ; i<2 ; i++) { - mFb[i].version = sizeof(GGLSurface); - mFb[i].width = info.xres; - mFb[i].height = info.yres; - mFb[i].stride = finfo.line_length / (info.bits_per_pixel >> 3); - mFb[i].data = (GGLubyte*)(offscreen[i]); - mFb[i].format = GGL_PIXEL_FORMAT_RGB_565; - } - return fd; -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp deleted file mode 100644 index f1071cf..0000000 --- a/libs/ui/EGLNativeWindowSurface.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* -** -** Copyright 2007 The Android Open Source Project -** -** Licensed under the Apache License Version 2.0(the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing software -** distributed under the License is distributed on an "AS IS" BASIS -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_TAG "EGLNativeWindowSurface" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <cutils/log.h> -#include <cutils/atomic.h> - -#include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> -#include <ui/Rect.h> - -#include <EGL/egl.h> - -#include <pixelflinger/format.h> - -#include <ui/EGLNativeWindowSurface.h> - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface) - : EGLNativeSurface<EGLNativeWindowSurface>(), - mSurface(surface), mConnected(false) -{ - egl_native_window_t::magic = 0x600913; - egl_native_window_t::version = sizeof(egl_native_window_t); - egl_native_window_t::ident = 0; - egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef; - egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef; - egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers; - egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect; - egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect; - - DisplayInfo dinfo; - SurfaceComposerClient::getDisplayInfo(0, &dinfo); - egl_native_window_t::xdpi = dinfo.xdpi; - egl_native_window_t::ydpi = dinfo.ydpi; - egl_native_window_t::fps = dinfo.fps; - egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER; -} - -EGLNativeWindowSurface::~EGLNativeWindowSurface() -{ - disconnect(); - mSurface.clear(); - magic = 0; -} - -void EGLNativeWindowSurface::hook_incRef(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->incStrong(that); -} - -void EGLNativeWindowSurface::hook_decRef(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->decStrong(that); -} - -void EGLNativeWindowSurface::hook_connect(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->connect(); -} - -void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->disconnect(); -} - -uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - return that->swapBuffers(); -} - -void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h) -{ - mSurface->setSwapRectangle(Rect(l, t, l+w, t+h)); -} - -uint32_t EGLNativeWindowSurface::swapBuffers() -{ - const int w = egl_native_window_t::width; - const int h = egl_native_window_t::height; - const sp<Surface>& surface(mSurface); - Surface::SurfaceInfo info; - surface->unlockAndPost(); - surface->lock(&info); - // update the address of the buffer to draw to next - egl_native_window_t::base = intptr_t(info.base); - egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base); - - // update size if it changed - if (w != int(info.w) || h != int(info.h)) { - egl_native_window_t::width = info.w; - egl_native_window_t::height = info.h; - egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format); - egl_native_window_t::format = info.format; - return EGL_NATIVES_FLAG_SIZE_CHANGED; - } - return 0; -} - -void EGLNativeWindowSurface::connect() -{ - if (!mConnected) { - Surface::SurfaceInfo info; - mSurface->lock(&info); - mSurface->setSwapRectangle(Rect(info.w, info.h)); - mConnected = true; - - egl_native_window_t::width = info.w; - egl_native_window_t::height = info.h; - egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format); - egl_native_window_t::format = info.format; - egl_native_window_t::base = intptr_t(info.base); - egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base); - // FIXME: egl_native_window_t::memory_type used to be set from - // mSurface, but we wanted to break this dependency. We set it to - // GPU because the software rendered doesn't care, but the h/w - // accelerator needs it. Eventually, this value should go away - // completely, since memory will be managed by OpenGL. - egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU; - egl_native_window_t::fd = 0; - } -} - -void EGLNativeWindowSurface::disconnect() -{ - if (mConnected) { - mSurface->unlock(); - mConnected = false; - } -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp deleted file mode 100644 index 3b29b09..0000000 --- a/libs/ui/EventHub.cpp +++ /dev/null @@ -1,793 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// -// Handle events, like key input and vsync. -// -// The goal is to provide an optimized solution for Linux, not an -// implementation that works well across all platforms. We expect -// events to arrive on file descriptors, so that we can use a select() -// select() call to sleep. -// -// We can't select() on anything but network sockets in Windows, so we -// provide an alternative implementation of waitEvent for that platform. -// -#define LOG_TAG "EventHub" - -//#define LOG_NDEBUG 0 - -#include <ui/EventHub.h> -#include <hardware_legacy/power.h> - -#include <cutils/properties.h> -#include <utils/IServiceManager.h> -#include <utils/Log.h> -#include <utils/Timers.h> -#include <utils.h> - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <memory.h> -#include <errno.h> -#include <assert.h> - -#include "KeyLayoutMap.h" - -#include <string.h> -#include <stdint.h> -#include <dirent.h> -#ifdef HAVE_INOTIFY -# include <sys/inotify.h> -#endif -#ifdef HAVE_ANDROID_OS -# include <sys/limits.h> /* not part of Linux */ -#endif -#include <sys/poll.h> -#include <sys/ioctl.h> - -/* this macro is used to tell if "bit" is set in "array" - * it selects a byte from the array, and does a boolean AND - * operation with a byte that only has the relevant bit set. - * eg. to check for the 12th bit, we do (array[1] & 1<<4) - */ -#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) - -#define ID_MASK 0x0000ffff -#define SEQ_MASK 0x7fff0000 -#define SEQ_SHIFT 16 -#define id_to_index(id) ((id&ID_MASK)+1) - -namespace android { - -static const char *WAKE_LOCK_ID = "KeyEvents"; -static const char *device_path = "/dev/input"; - -/* return the larger integer */ -static inline int max(int v1, int v2) -{ - return (v1 > v2) ? v1 : v2; -} - -EventHub::device_t::device_t(int32_t _id, const char* _path) - : id(_id), path(_path), classes(0) - , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) { -} - -EventHub::device_t::~device_t() { - delete [] keyBitmask; - delete layoutMap; -} - -EventHub::EventHub(void) - : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(0) - , mDevicesById(0), mNumDevicesById(0) - , mOpeningDevices(0), mClosingDevices(0) - , mDevices(0), mFDs(0), mFDCount(0) -{ - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); -#ifdef EV_SW - memset(mSwitches, 0, sizeof(mSwitches)); -#endif -} - -/* - * Clean up. - */ -EventHub::~EventHub(void) -{ - release_wake_lock(WAKE_LOCK_ID); - // we should free stuff here... -} - -void EventHub::onFirstRef() -{ - mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR; -} - -status_t EventHub::errorCheck() const -{ - return mError; -} - -String8 EventHub::getDeviceName(int32_t deviceId) const -{ - AutoMutex _l(mLock); - device_t* device = getDevice(deviceId); - if (device == NULL) return String8(); - return device->name; -} - -uint32_t EventHub::getDeviceClasses(int32_t deviceId) const -{ - AutoMutex _l(mLock); - device_t* device = getDevice(deviceId); - if (device == NULL) return 0; - return device->classes; -} - -int EventHub::getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue, - int* outMaxValue, int* outFlat, int* outFuzz) const -{ - AutoMutex _l(mLock); - device_t* device = getDevice(deviceId); - if (device == NULL) return -1; - - struct input_absinfo info; - - if(ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGABS(axis), &info)) { - LOGE("Error reading absolute controller %d for device %s fd %d\n", - axis, device->name.string(), mFDs[id_to_index(device->id)].fd); - return -1; - } - *outMinValue = info.minimum; - *outMaxValue = info.maximum; - *outFlat = info.flat; - *outFuzz = info.fuzz; - return 0; -} - -int EventHub::getSwitchState(int sw) const -{ -#ifdef EV_SW - if (sw >= 0 && sw <= SW_MAX) { - int32_t devid = mSwitches[sw]; - if (devid != 0) { - return getSwitchState(devid, sw); - } - } -#endif - return -1; -} - -int EventHub::getSwitchState(int32_t deviceId, int sw) const -{ -#ifdef EV_SW - AutoMutex _l(mLock); - device_t* device = getDevice(deviceId); - if (device == NULL) return -1; - - if (sw >= 0 && sw <= SW_MAX) { - uint8_t sw_bitmask[(SW_MAX+1)/8]; - memset(sw_bitmask, 0, sizeof(sw_bitmask)); - if (ioctl(mFDs[id_to_index(device->id)].fd, - EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) { - return test_bit(sw, sw_bitmask) ? 1 : 0; - } - } -#endif - - return -1; -} - -int EventHub::getScancodeState(int code) const -{ - return getScancodeState(mFirstKeyboardId, code); -} - -int EventHub::getScancodeState(int32_t deviceId, int code) const -{ - AutoMutex _l(mLock); - device_t* device = getDevice(deviceId); - if (device == NULL) return -1; - - if (code >= 0 && code <= KEY_MAX) { - uint8_t key_bitmask[(KEY_MAX+1)/8]; - memset(key_bitmask, 0, sizeof(key_bitmask)); - if (ioctl(mFDs[id_to_index(device->id)].fd, - EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { - return test_bit(code, key_bitmask) ? 1 : 0; - } - } - - return -1; -} - -int EventHub::getKeycodeState(int code) const -{ - return getKeycodeState(mFirstKeyboardId, code); -} - -int EventHub::getKeycodeState(int32_t deviceId, int code) const -{ - AutoMutex _l(mLock); - device_t* device = getDevice(deviceId); - if (device == NULL || device->layoutMap == NULL) return -1; - - Vector<int32_t> scanCodes; - device->layoutMap->findScancodes(code, &scanCodes); - - uint8_t key_bitmask[(KEY_MAX+1)/8]; - memset(key_bitmask, 0, sizeof(key_bitmask)); - if (ioctl(mFDs[id_to_index(device->id)].fd, - EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { - #if 0 - for (size_t i=0; i<=KEY_MAX; i++) { - LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask)); - } - #endif - const size_t N = scanCodes.size(); - for (size_t i=0; i<N && i<=KEY_MAX; i++) { - int32_t sc = scanCodes.itemAt(i); - //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask)); - if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) { - return 1; - } - } - } - - return 0; -} - -EventHub::device_t* EventHub::getDevice(int32_t deviceId) const -{ - if (deviceId == 0) deviceId = mFirstKeyboardId; - int32_t id = deviceId & ID_MASK; - if (id >= mNumDevicesById || id < 0) return NULL; - device_t* dev = mDevicesById[id].device; - if (dev->id == deviceId) { - return dev; - } - return NULL; -} - -bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType, - int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags, - int32_t* outValue, nsecs_t* outWhen) -{ - *outDeviceId = 0; - *outType = 0; - *outScancode = 0; - *outKeycode = 0; - *outFlags = 0; - *outValue = 0; - *outWhen = 0; - - status_t err; - - fd_set readfds; - int maxFd = -1; - int cc; - int i; - int res; - int pollres; - struct input_event iev; - - // Note that we only allow one caller to getEvent(), so don't need - // to do locking here... only when adding/removing devices. - - while(1) { - - // First, report any devices that had last been added/removed. - if (mClosingDevices != NULL) { - device_t* device = mClosingDevices; - LOGV("Reporting device closed: id=0x%x, name=%s\n", - device->id, device->path.string()); - mClosingDevices = device->next; - *outDeviceId = device->id; - if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0; - *outType = DEVICE_REMOVED; - delete device; - return true; - } - if (mOpeningDevices != NULL) { - device_t* device = mOpeningDevices; - LOGV("Reporting device opened: id=0x%x, name=%s\n", - device->id, device->path.string()); - mOpeningDevices = device->next; - *outDeviceId = device->id; - if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0; - *outType = DEVICE_ADDED; - return true; - } - - release_wake_lock(WAKE_LOCK_ID); - - pollres = poll(mFDs, mFDCount, -1); - - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); - - if (pollres <= 0) { - if (errno != EINTR) { - LOGW("select failed (errno=%d)\n", errno); - usleep(100000); - } - continue; - } - - //printf("poll %d, returned %d\n", mFDCount, pollres); - - // mFDs[0] is used for inotify, so process regular events starting at mFDs[1] - for(i = 1; i < mFDCount; i++) { - if(mFDs[i].revents) { - LOGV("revents for %d = 0x%08x", i, mFDs[i].revents); - if(mFDs[i].revents & POLLIN) { - res = read(mFDs[i].fd, &iev, sizeof(iev)); - if (res == sizeof(iev)) { - LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", - mDevices[i]->path.string(), - (int) iev.time.tv_sec, (int) iev.time.tv_usec, - iev.type, iev.code, iev.value); - *outDeviceId = mDevices[i]->id; - if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0; - *outType = iev.type; - *outScancode = iev.code; - if (iev.type == EV_KEY) { - err = mDevices[i]->layoutMap->map(iev.code, outKeycode, outFlags); - LOGV("iev.code=%d outKeycode=%d outFlags=0x%08x err=%d\n", - iev.code, *outKeycode, *outFlags, err); - if (err != 0) { - *outKeycode = 0; - *outFlags = 0; - } - } else { - *outKeycode = iev.code; - } - *outValue = iev.value; - *outWhen = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec); - return true; - } else { - if (res<0) { - LOGW("could not get event (errno=%d)", errno); - } else { - LOGE("could not get event (wrong size: %d)", res); - } - continue; - } - } - } - } - - // read_notify() will modify mFDs and mFDCount, so this must be done after - // processing all other events. - if(mFDs[0].revents & POLLIN) { - read_notify(mFDs[0].fd); - } - } -} - -/* - * Open the platform-specific input device. - */ -bool EventHub::openPlatformInput(void) -{ - /* - * Open platform-specific input device(s). - */ - int res; - - mFDCount = 1; - mFDs = (pollfd *)calloc(1, sizeof(mFDs[0])); - mDevices = (device_t **)calloc(1, sizeof(mDevices[0])); - mFDs[0].events = POLLIN; - mDevices[0] = NULL; -#ifdef HAVE_INOTIFY - mFDs[0].fd = inotify_init(); - res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE); - if(res < 0) { - LOGE("could not add watch for %s, %s\n", device_path, strerror(errno)); - } -#else - /* - * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd. - * We allocate space for it and set it to something invalid. - */ - mFDs[0].fd = -1; -#endif - - res = scan_dir(device_path); - if(res < 0) { - LOGE("scan dir failed for %s\n", device_path); - //open_device("/dev/input/event0"); - } - - return true; -} - -/* - * Inspect the known devices to determine whether physical keys exist for the given - * framework-domain key codes. - */ -bool EventHub::hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags) { - for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) { - outFlags[codeIndex] = 0; - - // check each available hardware device for support for this keycode - Vector<int32_t> scanCodes; - for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) { - if (mDevices[n]) { - status_t err = mDevices[n]->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes); - if (!err) { - // check the possible scan codes identified by the layout map against the - // map of codes actually emitted by the driver - for (size_t sc = 0; sc < scanCodes.size(); sc++) { - if (test_bit(scanCodes[sc], mDevices[n]->keyBitmask)) { - outFlags[codeIndex] = 1; - break; - } - } - } - } - } - } - - return true; -} - -// ---------------------------------------------------------------------------- - -int EventHub::open_device(const char *deviceName) -{ - int version; - int fd; - struct pollfd *new_mFDs; - device_t **new_devices; - char **new_device_names; - char name[80]; - char location[80]; - char idstr[80]; - struct input_id id; - - LOGV("Opening device: %s", deviceName); - - AutoMutex _l(mLock); - - fd = open(deviceName, O_RDWR); - if(fd < 0) { - LOGE("could not open %s, %s\n", deviceName, strerror(errno)); - return -1; - } - - if(ioctl(fd, EVIOCGVERSION, &version)) { - LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno)); - return -1; - } - if(ioctl(fd, EVIOCGID, &id)) { - LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno)); - return -1; - } - name[sizeof(name) - 1] = '\0'; - location[sizeof(location) - 1] = '\0'; - idstr[sizeof(idstr) - 1] = '\0'; - if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { - //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno)); - name[0] = '\0'; - } - if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) { - //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno)); - location[0] = '\0'; - } - if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) { - //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno)); - idstr[0] = '\0'; - } - - int devid = 0; - while (devid < mNumDevicesById) { - if (mDevicesById[devid].device == NULL) { - break; - } - devid++; - } - if (devid >= mNumDevicesById) { - device_ent* new_devids = (device_ent*)realloc(mDevicesById, - sizeof(mDevicesById[0]) * (devid + 1)); - if (new_devids == NULL) { - LOGE("out of memory"); - return -1; - } - mDevicesById = new_devids; - mNumDevicesById = devid+1; - mDevicesById[devid].device = NULL; - mDevicesById[devid].seq = 0; - } - - mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK; - if (mDevicesById[devid].seq == 0) { - mDevicesById[devid].seq = 1<<SEQ_SHIFT; - } - - new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1)); - new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1)); - if (new_mFDs == NULL || new_devices == NULL) { - LOGE("out of memory"); - return -1; - } - mFDs = new_mFDs; - mDevices = new_devices; - -#if 0 - LOGI("add device %d: %s\n", mFDCount, deviceName); - LOGI(" bus: %04x\n" - " vendor %04x\n" - " product %04x\n" - " version %04x\n", - id.bustype, id.vendor, id.product, id.version); - LOGI(" name: \"%s\"\n", name); - LOGI(" location: \"%s\"\n" - " id: \"%s\"\n", location, idstr); - LOGI(" version: %d.%d.%d\n", - version >> 16, (version >> 8) & 0xff, version & 0xff); -#endif - - device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName); - if (device == NULL) { - LOGE("out of memory"); - return -1; - } - - mFDs[mFDCount].fd = fd; - mFDs[mFDCount].events = POLLIN; - - // figure out the kinds of events the device reports - uint8_t key_bitmask[(KEY_MAX+1)/8]; - memset(key_bitmask, 0, sizeof(key_bitmask)); - LOGV("Getting keys..."); - if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) { - //LOGI("MAP\n"); - //for (int i=0; i<((KEY_MAX+1)/8); i++) { - // LOGI("%d: 0x%02x\n", i, key_bitmask[i]); - //} - for (int i=0; i<((BTN_MISC+7)/8); i++) { - if (key_bitmask[i] != 0) { - device->classes |= CLASS_KEYBOARD; - // 'Q' key support = cheap test of whether this is an alpha-capable kbd - if (test_bit(KEY_Q, key_bitmask)) { - device->classes |= CLASS_ALPHAKEY; - } - break; - } - } - if ((device->classes & CLASS_KEYBOARD) != 0) { - device->keyBitmask = new uint8_t[(KEY_MAX+1)/8]; - if (device->keyBitmask != NULL) { - memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask)); - } else { - delete device; - LOGE("out of memory allocating key bitmask"); - return -1; - } - } - } - if (test_bit(BTN_MOUSE, key_bitmask)) { - uint8_t rel_bitmask[(REL_MAX+1)/8]; - memset(rel_bitmask, 0, sizeof(rel_bitmask)); - LOGV("Getting relative controllers..."); - if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) - { - if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) { - device->classes |= CLASS_TRACKBALL; - } - } - } - if (test_bit(BTN_TOUCH, key_bitmask)) { - uint8_t abs_bitmask[(ABS_MAX+1)/8]; - memset(abs_bitmask, 0, sizeof(abs_bitmask)); - LOGV("Getting absolute controllers..."); - if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) - { - if (test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) { - device->classes |= CLASS_TOUCHSCREEN; - } - } - } - -#ifdef EV_SW - // figure out the switches this device reports - uint8_t sw_bitmask[(SW_MAX+1)/8]; - memset(sw_bitmask, 0, sizeof(sw_bitmask)); - if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) { - for (int i=0; i<EV_SW; i++) { - //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask)); - if (test_bit(i, sw_bitmask)) { - if (mSwitches[i] == 0) { - mSwitches[i] = device->id; - } - } - } - } -#endif - - LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n", - deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes); - - if ((device->classes&CLASS_KEYBOARD) != 0) { - char devname[101]; - char tmpfn[101]; - char keylayoutFilename[300]; - - // a more descriptive name - ioctl(mFDs[mFDCount].fd, EVIOCGNAME(sizeof(devname)-1), devname); - devname[sizeof(devname)-1] = 0; - device->name = devname; - - // replace all the spaces with underscores - strcpy(tmpfn, devname); - for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' ')) - *p = '_'; - - // find the .kl file we need for this device - const char* root = getenv("ANDROID_ROOT"); - snprintf(keylayoutFilename, sizeof(keylayoutFilename), - "%s/usr/keylayout/%s.kl", root, tmpfn); - bool defaultKeymap = false; - if (access(keylayoutFilename, R_OK)) { - snprintf(keylayoutFilename, sizeof(keylayoutFilename), - "%s/usr/keylayout/%s", root, "qwerty.kl"); - defaultKeymap = true; - } - device->layoutMap->load(keylayoutFilename); - - // tell the world about the devname (the descriptive name) - int32_t publicID; - if (!mHaveFirstKeyboard && !defaultKeymap) { - publicID = 0; - // the built-in keyboard has a well-known device ID of 0, - // this device better not go away. - mHaveFirstKeyboard = true; - mFirstKeyboardId = device->id; - } else { - publicID = device->id; - // ensure mFirstKeyboardId is set to -something-. - if (mFirstKeyboardId == 0) { - mFirstKeyboardId = device->id; - } - } - char propName[100]; - sprintf(propName, "hw.keyboards.%u.devname", publicID); - property_set(propName, devname); - - LOGI("New keyboard: publicID=%d device->id=%d devname='%s' propName='%s' keylayout='%s'\n", - publicID, device->id, devname, propName, keylayoutFilename); - } - - LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n", - deviceName, device, mFDCount, devid, device->classes); - - mDevicesById[devid].device = device; - device->next = mOpeningDevices; - mOpeningDevices = device; - mDevices[mFDCount] = device; - - mFDCount++; - return 0; -} - -int EventHub::close_device(const char *deviceName) -{ - AutoMutex _l(mLock); - - int i; - for(i = 1; i < mFDCount; i++) { - if(strcmp(mDevices[i]->path.string(), deviceName) == 0) { - //LOGD("remove device %d: %s\n", i, deviceName); - device_t* device = mDevices[i]; - int count = mFDCount - i - 1; - int index = (device->id&ID_MASK); - mDevicesById[index].device = NULL; - memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count); - memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count); - -#ifdef EV_SW - for (int j=0; j<EV_SW; j++) { - if (mSwitches[j] == device->id) { - mSwitches[j] = 0; - } - } -#endif - - device->next = mClosingDevices; - mClosingDevices = device; - - mFDCount--; - - uint32_t publicID; - if (device->id == mFirstKeyboardId) { - LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this", - device->path.string(), mFirstKeyboardId); - mFirstKeyboardId = 0; - publicID = 0; - } else { - publicID = device->id; - } - // clear the property - char propName[100]; - sprintf(propName, "hw.keyboards.%u.devname", publicID); - property_set(propName, NULL); - return 0; - } - } - LOGE("remote device: %s not found\n", deviceName); - return -1; -} - -int EventHub::read_notify(int nfd) -{ -#ifdef HAVE_INOTIFY - int res; - char devname[PATH_MAX]; - char *filename; - char event_buf[512]; - int event_size; - int event_pos = 0; - struct inotify_event *event; - - res = read(nfd, event_buf, sizeof(event_buf)); - if(res < (int)sizeof(*event)) { - if(errno == EINTR) - return 0; - LOGW("could not get event, %s\n", strerror(errno)); - return 1; - } - //printf("got %d bytes of event information\n", res); - - strcpy(devname, device_path); - filename = devname + strlen(devname); - *filename++ = '/'; - - while(res >= (int)sizeof(*event)) { - event = (struct inotify_event *)(event_buf + event_pos); - //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : ""); - if(event->len) { - strcpy(filename, event->name); - if(event->mask & IN_CREATE) { - open_device(devname); - } - else { - close_device(devname); - } - } - event_size = sizeof(*event) + event->len; - res -= event_size; - event_pos += event_size; - } -#endif - return 0; -} - - -int EventHub::scan_dir(const char *dirname) -{ - char devname[PATH_MAX]; - char *filename; - DIR *dir; - struct dirent *de; - dir = opendir(dirname); - if(dir == NULL) - return -1; - strcpy(devname, dirname); - filename = devname + strlen(devname); - *filename++ = '/'; - while((de = readdir(dir))) { - if(de->d_name[0] == '.' && - (de->d_name[1] == '\0' || - (de->d_name[1] == '.' && de->d_name[2] == '\0'))) - continue; - strcpy(filename, de->d_name); - open_device(devname); - } - closedir(dir); - return 0; -} - -}; // namespace android diff --git a/libs/ui/EventRecurrence.cpp b/libs/ui/EventRecurrence.cpp deleted file mode 100644 index b436b50..0000000 --- a/libs/ui/EventRecurrence.cpp +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - */ - -#include <pim/EventRecurrence.h> -#include <utils/String8.h> -#include <stdio.h> -#include <limits.h> - -namespace android { - -#define FAIL_HERE() do { \ - printf("Parsing failed at line %d\n", __LINE__); \ - return UNKNOWN_ERROR; \ - } while(0) - -EventRecurrence::EventRecurrence() - :freq((freq_t)0), - until(), - count(0), - interval(0), - bysecond(0), - bysecondCount(0), - byminute(0), - byminuteCount(0), - byhour(0), - byhourCount(0), - byday(0), - bydayNum(0), - bydayCount(0), - bymonthday(0), - bymonthdayCount(0), - byyearday(0), - byyeardayCount(0), - byweekno(0), - byweeknoCount(0), - bymonth(0), - bymonthCount(0), - bysetpos(0), - bysetposCount(0), - wkst(0) -{ -} - -EventRecurrence::~EventRecurrence() -{ - delete[] bysecond; - delete[] byminute; - delete[] byhour; - delete[] byday; - delete[] bydayNum; - delete[] byyearday; - delete[] bymonthday; - delete[] byweekno; - delete[] bymonth; - delete[] bysetpos; -} - -enum LHS { - NONE_LHS = 0, - FREQ, - UNTIL, - COUNT, - INTERVAL, - BYSECOND, - BYMINUTE, - BYHOUR, - BYDAY, - BYMONTHDAY, - BYYEARDAY, - BYWEEKNO, - BYMONTH, - BYSETPOS, - WKST -}; - -struct LHSProc -{ - const char16_t* text; - size_t textSize; - uint32_t value; -}; - -const char16_t FREQ_text[] = { 'F', 'R', 'E', 'Q' }; -const char16_t UNTIL_text[] = { 'U', 'N', 'T', 'I', 'L' }; -const char16_t COUNT_text[] = { 'C', 'O', 'U', 'N', 'T' }; -const char16_t INTERVAL_text[] = { 'I', 'N', 'T', 'E', 'R', 'V', 'A', 'L'}; -const char16_t BYSECOND_text[] = { 'B', 'Y', 'S', 'E', 'C', 'O', 'N', 'D' }; -const char16_t BYMINUTE_text[] = { 'B', 'Y', 'M', 'I', 'N', 'U', 'T', 'E' }; -const char16_t BYHOUR_text[] = { 'B', 'Y', 'H', 'O', 'U', 'R' }; -const char16_t BYDAY_text[] = { 'B', 'Y', 'D', 'A', 'Y' }; -const char16_t BYMONTHDAY_text[] = { 'B','Y','M','O','N','T','H','D','A','Y' }; -const char16_t BYYEARDAY_text[] = { 'B','Y','Y','E','A','R','D','A','Y' }; -const char16_t BYWEEKNO_text[] = { 'B', 'Y', 'W', 'E', 'E', 'K', 'N', 'O' }; -const char16_t BYMONTH_text[] = { 'B', 'Y', 'M', 'O', 'N', 'T', 'H' }; -const char16_t BYSETPOS_text[] = { 'B', 'Y', 'S', 'E', 'T', 'P', 'O', 'S' }; -const char16_t WKST_text[] = { 'W', 'K', 'S', 'T' }; - -#define SIZ(x) (sizeof(x)/sizeof(x[0])) - -const LHSProc LHSPROC[] = { - { FREQ_text, SIZ(FREQ_text), FREQ }, - { UNTIL_text, SIZ(UNTIL_text), UNTIL }, - { COUNT_text, SIZ(COUNT_text), COUNT }, - { INTERVAL_text, SIZ(INTERVAL_text), INTERVAL }, - { BYSECOND_text, SIZ(BYSECOND_text), BYSECOND }, - { BYMINUTE_text, SIZ(BYMINUTE_text), BYMINUTE }, - { BYHOUR_text, SIZ(BYHOUR_text), BYHOUR }, - { BYDAY_text, SIZ(BYDAY_text), BYDAY }, - { BYMONTHDAY_text, SIZ(BYMONTHDAY_text), BYMONTHDAY }, - { BYYEARDAY_text, SIZ(BYYEARDAY_text), BYYEARDAY }, - { BYWEEKNO_text, SIZ(BYWEEKNO_text), BYWEEKNO }, - { BYMONTH_text, SIZ(BYMONTH_text), BYMONTH }, - { BYSETPOS_text, SIZ(BYSETPOS_text), BYSETPOS }, - { WKST_text, SIZ(WKST_text), WKST }, - { NULL, 0, NONE_LHS }, -}; - -const char16_t SECONDLY_text[] = { 'S','E','C','O','N','D','L','Y' }; -const char16_t MINUTELY_text[] = { 'M','I','N','U','T','E','L','Y' }; -const char16_t HOURLY_text[] = { 'H','O','U','R','L','Y' }; -const char16_t DAILY_text[] = { 'D','A','I','L','Y' }; -const char16_t WEEKLY_text[] = { 'W','E','E','K','L','Y' }; -const char16_t MONTHLY_text[] = { 'M','O','N','T','H','L','Y' }; -const char16_t YEARLY_text[] = { 'Y','E','A','R','L','Y' }; - -typedef LHSProc FreqProc; - -const FreqProc FREQPROC[] = { - { SECONDLY_text, SIZ(SECONDLY_text), EventRecurrence::SECONDLY }, - { MINUTELY_text, SIZ(MINUTELY_text), EventRecurrence::MINUTELY }, - { HOURLY_text, SIZ(HOURLY_text), EventRecurrence::HOURLY }, - { DAILY_text, SIZ(DAILY_text), EventRecurrence::DAILY }, - { WEEKLY_text, SIZ(WEEKLY_text), EventRecurrence::WEEKLY }, - { MONTHLY_text, SIZ(MONTHLY_text), EventRecurrence::MONTHLY }, - { YEARLY_text, SIZ(YEARLY_text), EventRecurrence::YEARLY }, - { NULL, 0, NONE_LHS }, -}; - -const char16_t SU_text[] = { 'S','U' }; -const char16_t MO_text[] = { 'M','O' }; -const char16_t TU_text[] = { 'T','U' }; -const char16_t WE_text[] = { 'W','E' }; -const char16_t TH_text[] = { 'T','H' }; -const char16_t FR_text[] = { 'F','R' }; -const char16_t SA_text[] = { 'S','A' }; - -const FreqProc WEEKDAYPROC[] = { - { SU_text, SIZ(SU_text), EventRecurrence::SU }, - { MO_text, SIZ(MO_text), EventRecurrence::MO }, - { TU_text, SIZ(TU_text), EventRecurrence::TU }, - { WE_text, SIZ(WE_text), EventRecurrence::WE }, - { TH_text, SIZ(TH_text), EventRecurrence::TH }, - { FR_text, SIZ(FR_text), EventRecurrence::FR }, - { SA_text, SIZ(SA_text), EventRecurrence::SA }, - { NULL, 0, NONE_LHS }, -}; - -// returns the index into LHSPROC for the match or -1 if not found -inline static int -match_proc(const LHSProc* p, const char16_t* str, size_t len) -{ - int i = 0; - while (p->text != NULL) { - if (p->textSize == len) { - if (0 == memcmp(p->text, str, len*sizeof(char16_t))) { - return i; - } - } - p++; - i++; - } - return -1; -} - -// rangeMin and rangeMax are inclusive -static status_t -parse_int(const char16_t* str, size_t len, int* out, - int rangeMin, int rangeMax, bool zeroOK) -{ - char16_t c; - size_t i=0; - - if (len == 0) { - FAIL_HERE(); - } - bool negative = false; - c = str[0]; - if (c == '-' ) { - negative = true; - i++; - } - else if (c == '+') { - i++; - } - int n = 0; - for (; i<len; i++) { - c = str[i]; - if (c < '0' || c > '9') { - FAIL_HERE(); - } - int prev = n; - n *= 10; - // the spec doesn't address how big these numbers can be, - // so we're not going to worry about not being able to represent - // INT_MIN, and if we're going to wrap, we'll just clamp to - // INT_MAX instead - if (n < prev) { - n = INT_MAX; - } else { - n += c - '0'; - } - } - if (negative) { - n = -n; - } - if (n < rangeMin || n > rangeMax) { - FAIL_HERE(); - } - if (!zeroOK && n == 0) { - FAIL_HERE(); - } - *out = n; - return NO_ERROR; -} - -static status_t -parse_int_list(const char16_t* str, size_t len, int* countOut, int** listOut, - int rangeMin, int rangeMax, bool zeroOK, - status_t (*func)(const char16_t*,size_t,int*,int,int,bool)=parse_int) -{ - status_t err; - - if (len == 0) { - *countOut = 0; - *listOut = NULL; - return NO_ERROR; - } - - // make one pass through looking for commas so we know how big to make our - // out array. - int count = 1; - for (size_t i=0; i<len; i++) { - if (str[i] == ',') { - count++; - } - } - - int* list = new int[count]; - const char16_t* p = str; - int commaIndex = 0; - size_t i; - - for (i=0; i<len; i++) { - if (str[i] == ',') { - err = func(p, (str+i-p), list+commaIndex, rangeMin, - rangeMax, zeroOK); - if (err != NO_ERROR) { - goto bail; - } - commaIndex++; - p = str+i+1; - } - } - - err = func(p, (str+i-p), list+commaIndex, rangeMin, rangeMax, zeroOK); - if (err != NO_ERROR) { - goto bail; - } - commaIndex++; - - *countOut = count; - *listOut = list; - - return NO_ERROR; - -bail: - delete[] list; - FAIL_HERE(); -} - -// the numbers here are small, so we pack them both into one value, and then -// split it out later. it lets us reuse all the comma separated list code. -static status_t -parse_byday(const char16_t* s, size_t len, int* out, - int rangeMin, int rangeMax, bool zeroOK) -{ - status_t err; - int n = 0; - const char16_t* p = s; - size_t plen = len; - - if (len > 0) { - char16_t c = s[0]; - if (c == '-' || c == '+' || (c >= '0' && c <= '9')) { - if (len > 1) { - size_t nlen = 0; - c = s[nlen]; - while (nlen < len - && (c == '-' || c == '+' || (c >= '0' && c <= '9'))) { - c = s[nlen]; - nlen++; - } - if (nlen > 0) { - nlen--; - err = parse_int(s, nlen, &n, rangeMin, rangeMax, zeroOK); - if (err != NO_ERROR) { - FAIL_HERE(); - } - p += nlen; - plen -= nlen; - } - } - } - - int index = match_proc(WEEKDAYPROC, p, plen); - if (index >= 0) { - *out = (0xffff0000 & WEEKDAYPROC[index].value) - | (0x0000ffff & n); - return NO_ERROR; - } - } - return UNKNOWN_ERROR; -} - -static void -postprocess_byday(int count, int* byday, int** bydayNum) -{ - int* bdn = new int[count]; - *bydayNum = bdn; - for (int i=0; i<count; i++) { - uint32_t v = byday[i]; - int16_t num = v & 0x0000ffff; - byday[i] = v & 0xffff0000; - // will sign extend: - bdn[i] = num; - } -} - -#define PARSE_INT_LIST_CHECKED(name, rangeMin, rangeMax, zeroOK) \ - if (name##Count != 0 || NO_ERROR != parse_int_list(s, slen, \ - &name##Count, &name, rangeMin, rangeMax, zeroOK)) { \ - FAIL_HERE(); \ - } -status_t -EventRecurrence::parse(const String16& str) -{ - char16_t const* work = str.string(); - size_t len = str.size(); - - int lhsIndex = NONE_LHS; - int index; - - size_t start = 0; - for (size_t i=0; i<len; i++) { - char16_t c = work[i]; - if (c != ';' && i == len-1) { - c = ';'; - i++; - } - if (c == ';' || c == '=') { - if (i != start) { - const char16_t* s = work+start; - const size_t slen = i-start; - - String8 thestring(String16(s, slen)); - - switch (c) - { - case '=': - if (lhsIndex == NONE_LHS) { - lhsIndex = match_proc(LHSPROC, s, slen); - if (lhsIndex >= 0) { - break; - } - } - FAIL_HERE(); - case ';': - { - switch (LHSPROC[lhsIndex].value) - { - case FREQ: - if (this->freq != 0) { - FAIL_HERE(); - } - index = match_proc(FREQPROC, s, slen); - if (index >= 0) { - this->freq = (freq_t)FREQPROC[index].value; - } - break; - case UNTIL: - // XXX should check that this is a valid time - until.setTo(String16(s, slen)); - break; - case COUNT: - if (count != 0 - || NO_ERROR != parse_int(s, slen, - &count, INT_MIN, INT_MAX, true)) { - FAIL_HERE(); - } - break; - case INTERVAL: - if (interval != 0 - || NO_ERROR != parse_int(s, slen, - &interval, INT_MIN, INT_MAX, false)) { - FAIL_HERE(); - } - break; - case BYSECOND: - PARSE_INT_LIST_CHECKED(bysecond, 0, 59, true) - break; - case BYMINUTE: - PARSE_INT_LIST_CHECKED(byminute, 0, 59, true) - break; - case BYHOUR: - PARSE_INT_LIST_CHECKED(byhour, 0, 23, true) - break; - case BYDAY: - if (bydayCount != 0 || NO_ERROR != - parse_int_list(s, slen, &bydayCount, - &byday, -53, 53, false, - parse_byday)) { - FAIL_HERE(); - } - postprocess_byday(bydayCount, byday, &bydayNum); - break; - case BYMONTHDAY: - PARSE_INT_LIST_CHECKED(bymonthday, -31, 31, - false) - break; - case BYYEARDAY: - PARSE_INT_LIST_CHECKED(byyearday, -366, 366, - false) - break; - case BYWEEKNO: - PARSE_INT_LIST_CHECKED(byweekno, -53, 53, - false) - break; - case BYMONTH: - PARSE_INT_LIST_CHECKED(bymonth, 1, 12, false) - break; - case BYSETPOS: - PARSE_INT_LIST_CHECKED(bysetpos, - INT_MIN, INT_MAX, true) - break; - case WKST: - if (this->wkst != 0) { - FAIL_HERE(); - } - index = match_proc(WEEKDAYPROC, s, slen); - if (index >= 0) { - this->wkst = (int)WEEKDAYPROC[index].value; - } - break; - default: - FAIL_HERE(); - } - lhsIndex = NONE_LHS; - break; - } - } - - start = i+1; - } - } - } - - // enforce that there was a FREQ - if (freq == 0) { - FAIL_HERE(); - } - - // default wkst to MO if it wasn't specified - if (wkst == 0) { - wkst = MO; - } - - return NO_ERROR; -} - - -}; // namespace android - - diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp deleted file mode 100644 index ab0fef1..0000000 --- a/libs/ui/ICamera.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* -** -** Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "ICamera" -#include <utils/Log.h> -#include <stdint.h> -#include <sys/types.h> -#include <utils/Parcel.h> -#include <ui/ICamera.h> - -namespace android { - -enum { - DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, - SET_PREVIEW_DISPLAY, - SET_PREVIEW_CALLBACK_FLAG, - START_PREVIEW, - STOP_PREVIEW, - AUTO_FOCUS, - TAKE_PICTURE, - SET_PARAMETERS, - GET_PARAMETERS, - CONNECT, - LOCK, - UNLOCK, - PREVIEW_ENABLED, - START_RECORDING, - STOP_RECORDING, - RECORDING_ENABLED, - RELEASE_RECORDING_FRAME, -}; - -class BpCamera: public BpInterface<ICamera> -{ -public: - BpCamera(const sp<IBinder>& impl) - : BpInterface<ICamera>(impl) - { - } - - // disconnect from camera service - void disconnect() - { - LOGV("disconnect"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(DISCONNECT, data, &reply); - } - - // pass the buffered ISurface to the camera service - status_t setPreviewDisplay(const sp<ISurface>& surface) - { - LOGV("setPreviewDisplay"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - data.writeStrongBinder(surface->asBinder()); - remote()->transact(SET_PREVIEW_DISPLAY, data, &reply); - return reply.readInt32(); - } - - // set the preview callback flag to affect how the received frames from - // preview are handled. See Camera.h for details. - void setPreviewCallbackFlag(int flag) - { - LOGV("setPreviewCallbackFlag(%d)", flag); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - data.writeInt32(flag); - remote()->transact(SET_PREVIEW_CALLBACK_FLAG, data, &reply); - } - - // start preview mode, must call setPreviewDisplay first - status_t startPreview() - { - LOGV("startPreview"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(START_PREVIEW, data, &reply); - return reply.readInt32(); - } - - // start recording mode, must call setPreviewDisplay first - status_t startRecording() - { - LOGV("startRecording"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(START_RECORDING, data, &reply); - return reply.readInt32(); - } - - // stop preview mode - void stopPreview() - { - LOGV("stopPreview"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(STOP_PREVIEW, data, &reply); - } - - // stop recording mode - void stopRecording() - { - LOGV("stopRecording"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(STOP_RECORDING, data, &reply); - } - - void releaseRecordingFrame(const sp<IMemory>& mem) - { - LOGV("releaseRecordingFrame"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - data.writeStrongBinder(mem->asBinder()); - remote()->transact(RELEASE_RECORDING_FRAME, data, &reply); - } - - // check preview state - bool previewEnabled() - { - LOGV("previewEnabled"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(PREVIEW_ENABLED, data, &reply); - return reply.readInt32(); - } - - // check recording state - bool recordingEnabled() - { - LOGV("recordingEnabled"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(RECORDING_ENABLED, data, &reply); - return reply.readInt32(); - } - - // auto focus - status_t autoFocus() - { - LOGV("autoFocus"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(AUTO_FOCUS, data, &reply); - status_t ret = reply.readInt32(); - return ret; - } - - // take a picture - returns an IMemory (ref-counted mmap) - status_t takePicture() - { - LOGV("takePicture"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(TAKE_PICTURE, data, &reply); - status_t ret = reply.readInt32(); - return ret; - } - - // set preview/capture parameters - key/value pairs - status_t setParameters(const String8& params) - { - LOGV("setParameters"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - data.writeString8(params); - remote()->transact(SET_PARAMETERS, data, &reply); - return reply.readInt32(); - } - - // get preview/capture parameters - key/value pairs - String8 getParameters() const - { - LOGV("getParameters"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(GET_PARAMETERS, data, &reply); - return reply.readString8(); - } - virtual status_t connect(const sp<ICameraClient>& cameraClient) - { - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - data.writeStrongBinder(cameraClient->asBinder()); - remote()->transact(CONNECT, data, &reply); - return reply.readInt32(); - } - virtual status_t lock() - { - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(LOCK, data, &reply); - return reply.readInt32(); - } - virtual status_t unlock() - { - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(UNLOCK, data, &reply); - return reply.readInt32(); - } -}; - -IMPLEMENT_META_INTERFACE(Camera, "android.hardware.ICamera"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnCamera::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case DISCONNECT: { - LOGV("DISCONNECT"); - CHECK_INTERFACE(ICamera, data, reply); - disconnect(); - return NO_ERROR; - } break; - case SET_PREVIEW_DISPLAY: { - LOGV("SET_PREVIEW_DISPLAY"); - CHECK_INTERFACE(ICamera, data, reply); - sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder()); - reply->writeInt32(setPreviewDisplay(surface)); - return NO_ERROR; - } break; - case SET_PREVIEW_CALLBACK_FLAG: { - LOGV("SET_PREVIEW_CALLBACK_TYPE"); - CHECK_INTERFACE(ICamera, data, reply); - int callback_flag = data.readInt32(); - setPreviewCallbackFlag(callback_flag); - return NO_ERROR; - } break; - case START_PREVIEW: { - LOGV("START_PREVIEW"); - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(startPreview()); - return NO_ERROR; - } break; - case START_RECORDING: { - LOGV("START_RECORDING"); - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(startRecording()); - return NO_ERROR; - } break; - case STOP_PREVIEW: { - LOGV("STOP_PREVIEW"); - CHECK_INTERFACE(ICamera, data, reply); - stopPreview(); - return NO_ERROR; - } break; - case STOP_RECORDING: { - LOGV("STOP_RECORDING"); - CHECK_INTERFACE(ICamera, data, reply); - stopRecording(); - return NO_ERROR; - } break; - case RELEASE_RECORDING_FRAME: { - LOGV("RELEASE_RECORDING_FRAME"); - CHECK_INTERFACE(ICamera, data, reply); - sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder()); - releaseRecordingFrame(mem); - return NO_ERROR; - } break; - case PREVIEW_ENABLED: { - LOGV("PREVIEW_ENABLED"); - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(previewEnabled()); - return NO_ERROR; - } break; - case RECORDING_ENABLED: { - LOGV("RECORDING_ENABLED"); - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(recordingEnabled()); - return NO_ERROR; - } break; - case AUTO_FOCUS: { - LOGV("AUTO_FOCUS"); - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(autoFocus()); - return NO_ERROR; - } break; - case TAKE_PICTURE: { - LOGV("TAKE_PICTURE"); - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(takePicture()); - return NO_ERROR; - } break; - case SET_PARAMETERS: { - LOGV("SET_PARAMETERS"); - CHECK_INTERFACE(ICamera, data, reply); - String8 params(data.readString8()); - reply->writeInt32(setParameters(params)); - return NO_ERROR; - } break; - case GET_PARAMETERS: { - LOGV("GET_PARAMETERS"); - CHECK_INTERFACE(ICamera, data, reply); - reply->writeString8(getParameters()); - return NO_ERROR; - } break; - case CONNECT: { - CHECK_INTERFACE(ICamera, data, reply); - sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder()); - reply->writeInt32(connect(cameraClient)); - return NO_ERROR; - } break; - case LOCK: { - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(lock()); - return NO_ERROR; - } break; - case UNLOCK: { - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(unlock()); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android - diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp deleted file mode 100644 index 4bec9d2..0000000 --- a/libs/ui/ICameraClient.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* -** -** Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "ICameraClient" -#include <utils/Log.h> -#include <stdint.h> -#include <sys/types.h> -#include <ui/ICameraClient.h> - -namespace android { - -enum { - SHUTTER_CALLBACK = IBinder::FIRST_CALL_TRANSACTION, - RAW_CALLBACK, - JPEG_CALLBACK, - PREVIEW_CALLBACK, - ERROR_CALLBACK, - AUTOFOCUS_CALLBACK, - RECORDING_CALLBACK, -}; - -class BpCameraClient: public BpInterface<ICameraClient> -{ -public: - BpCameraClient(const sp<IBinder>& impl) - : BpInterface<ICameraClient>(impl) - { - } - - // callback to let the app know the shutter has closed, ideal for playing the shutter sound - void shutterCallback() - { - LOGV("shutterCallback"); - Parcel data, reply; - data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); - remote()->transact(SHUTTER_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); - } - - // callback from camera service to app with picture data - void rawCallback(const sp<IMemory>& picture) - { - LOGV("rawCallback"); - Parcel data, reply; - data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); - data.writeStrongBinder(picture->asBinder()); - remote()->transact(RAW_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); - } - - // callback from camera service to app with picture data - void jpegCallback(const sp<IMemory>& picture) - { - LOGV("jpegCallback"); - Parcel data, reply; - data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); - data.writeStrongBinder(picture->asBinder()); - remote()->transact(JPEG_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); - } - - // callback from camera service to app with preview frame data - void previewCallback(const sp<IMemory>& frame) - { - LOGV("previewCallback"); - Parcel data, reply; - data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); - data.writeStrongBinder(frame->asBinder()); - remote()->transact(PREVIEW_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); - } - - // callback from camera service to app with recording frame data - void recordingCallback(const sp<IMemory>& frame) - { - LOGV("recordingCallback"); - Parcel data, reply; - data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); - data.writeStrongBinder(frame->asBinder()); - remote()->transact(RECORDING_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); - } - - // callback from camera service to app to report error - void errorCallback(status_t error) - { - LOGV("errorCallback"); - Parcel data, reply; - data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); - data.writeInt32(error); - remote()->transact(ERROR_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); - } - - // callback from camera service to app to report autofocus completion - void autoFocusCallback(bool focused) - { - LOGV("autoFocusCallback"); - Parcel data, reply; - data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); - data.writeInt32(focused); - remote()->transact(AUTOFOCUS_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnCameraClient::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case SHUTTER_CALLBACK: { - LOGV("SHUTTER_CALLBACK"); - CHECK_INTERFACE(ICameraClient, data, reply); - shutterCallback(); - return NO_ERROR; - } break; - case RAW_CALLBACK: { - LOGV("RAW_CALLBACK"); - CHECK_INTERFACE(ICameraClient, data, reply); - sp<IMemory> picture = interface_cast<IMemory>(data.readStrongBinder()); - rawCallback(picture); - return NO_ERROR; - } break; - case JPEG_CALLBACK: { - LOGV("JPEG_CALLBACK"); - CHECK_INTERFACE(ICameraClient, data, reply); - sp<IMemory> picture = interface_cast<IMemory>(data.readStrongBinder()); - jpegCallback(picture); - return NO_ERROR; - } break; - case PREVIEW_CALLBACK: { - LOGV("PREVIEW_CALLBACK"); - CHECK_INTERFACE(ICameraClient, data, reply); - sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder()); - previewCallback(frame); - return NO_ERROR; - } break; - case RECORDING_CALLBACK: { - LOGV("RECORDING_CALLBACK"); - CHECK_INTERFACE(ICameraClient, data, reply); - sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder()); - recordingCallback(frame); - return NO_ERROR; - } break; - case ERROR_CALLBACK: { - LOGV("ERROR_CALLBACK"); - CHECK_INTERFACE(ICameraClient, data, reply); - status_t error = data.readInt32(); - errorCallback(error); - return NO_ERROR; - } break; - case AUTOFOCUS_CALLBACK: { - LOGV("AUTOFOCUS_CALLBACK"); - CHECK_INTERFACE(ICameraClient, data, reply); - bool focused = (bool)data.readInt32(); - autoFocusCallback(focused); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android - diff --git a/libs/ui/ICameraService.cpp b/libs/ui/ICameraService.cpp deleted file mode 100644 index e5687fe..0000000 --- a/libs/ui/ICameraService.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* -** -** Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Parcel.h> -#include <utils/IPCThreadState.h> -#include <utils/IServiceManager.h> - -#include <ui/ICameraService.h> - -namespace android { - -class BpCameraService: public BpInterface<ICameraService> -{ -public: - BpCameraService(const sp<IBinder>& impl) - : BpInterface<ICameraService>(impl) - { - } - - // connect to camera service - virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient) - { - Parcel data, reply; - data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); - data.writeStrongBinder(cameraClient->asBinder()); - remote()->transact(BnCameraService::CONNECT, data, &reply); - return interface_cast<ICamera>(reply.readStrongBinder()); - } -}; - -IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnCameraService::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case CONNECT: { - CHECK_INTERFACE(ICameraService, data, reply); - sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder()); - sp<ICamera> camera = connect(cameraClient); - reply->writeStrongBinder(camera->asBinder()); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android - diff --git a/libs/ui/IOverlay.cpp b/libs/ui/IOverlay.cpp deleted file mode 100644 index fed47c2..0000000 --- a/libs/ui/IOverlay.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Parcel.h> -#include <utils/IInterface.h> - -#include <ui/IOverlay.h> - -namespace android { - -enum { - DESTROY = IBinder::FIRST_CALL_TRANSACTION, // one-way transaction -}; - -class BpOverlay : public BpInterface<IOverlay> -{ -public: - BpOverlay(const sp<IBinder>& impl) - : BpInterface<IOverlay>(impl) - { - } - - virtual void destroy() - { - Parcel data, reply; - data.writeInterfaceToken(IOverlay::getInterfaceDescriptor()); - remote()->transact(DESTROY, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(Overlay, "android.ui.IOverlay"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnOverlay::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case DESTROY: { - CHECK_INTERFACE(IOverlay, data, reply); - destroy(); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp deleted file mode 100644 index d5e9f81..0000000 --- a/libs/ui/ISurface.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Parcel.h> -#include <utils/IMemory.h> - -#include <ui/ISurface.h> -#include <ui/Overlay.h> - - -namespace android { - -ISurface::BufferHeap::BufferHeap() - : w(0), h(0), hor_stride(0), ver_stride(0), format(0), - transform(0), flags(0) -{ -} - -ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h, - int32_t hor_stride, int32_t ver_stride, - PixelFormat format, const sp<IMemoryHeap>& heap) - : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride), - format(format), transform(0), flags(0), heap(heap) -{ -} - -ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h, - int32_t hor_stride, int32_t ver_stride, - PixelFormat format, uint32_t transform, uint32_t flags, - const sp<IMemoryHeap>& heap) - : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride), - format(format), transform(transform), flags(flags), heap(heap) -{ -} - - -ISurface::BufferHeap::~BufferHeap() -{ -} - -class BpSurface : public BpInterface<ISurface> -{ -public: - BpSurface(const sp<IBinder>& impl) - : BpInterface<ISurface>(impl) - { - } - - virtual status_t registerBuffers(const BufferHeap& buffers) - { - Parcel data, reply; - data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); - data.writeInt32(buffers.w); - data.writeInt32(buffers.h); - data.writeInt32(buffers.hor_stride); - data.writeInt32(buffers.ver_stride); - data.writeInt32(buffers.format); - data.writeInt32(buffers.transform); - data.writeInt32(buffers.flags); - data.writeStrongBinder(buffers.heap->asBinder()); - remote()->transact(REGISTER_BUFFERS, data, &reply); - status_t result = reply.readInt32(); - return result; - } - - virtual void postBuffer(ssize_t offset) - { - Parcel data, reply; - data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); - data.writeInt32(offset); - remote()->transact(POST_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); - } - - virtual void unregisterBuffers() - { - Parcel data, reply; - data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); - remote()->transact(UNREGISTER_BUFFERS, data, &reply); - } - - virtual sp<OverlayRef> createOverlay( - uint32_t w, uint32_t h, int32_t format) - { - Parcel data, reply; - data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - remote()->transact(CREATE_OVERLAY, data, &reply); - return OverlayRef::readFromParcel(reply); - } -}; - -IMPLEMENT_META_INTERFACE(Surface, "android.ui.ISurface"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnSurface::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case REGISTER_BUFFERS: { - CHECK_INTERFACE(ISurface, data, reply); - BufferHeap buffer; - buffer.w = data.readInt32(); - buffer.h = data.readInt32(); - buffer.hor_stride = data.readInt32(); - buffer.ver_stride= data.readInt32(); - buffer.format = data.readInt32(); - buffer.transform = data.readInt32(); - buffer.flags = data.readInt32(); - buffer.heap = interface_cast<IMemoryHeap>(data.readStrongBinder()); - status_t err = registerBuffers(buffer); - reply->writeInt32(err); - return NO_ERROR; - } break; - case UNREGISTER_BUFFERS: { - CHECK_INTERFACE(ISurface, data, reply); - unregisterBuffers(); - return NO_ERROR; - } break; - case POST_BUFFER: { - CHECK_INTERFACE(ISurface, data, reply); - ssize_t offset = data.readInt32(); - postBuffer(offset); - return NO_ERROR; - } break; - case CREATE_OVERLAY: { - CHECK_INTERFACE(ISurface, data, reply); - int w = data.readInt32(); - int h = data.readInt32(); - int f = data.readInt32(); - sp<OverlayRef> o = createOverlay(w, h, f); - return OverlayRef::writeToParcel(reply, o); - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp deleted file mode 100644 index 0fea6f9..0000000 --- a/libs/ui/ISurfaceComposer.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// tag as surfaceflinger -#define LOG_TAG "SurfaceFlinger" - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Parcel.h> -#include <utils/IMemory.h> -#include <utils/IPCThreadState.h> -#include <utils/IServiceManager.h> - -#include <ui/ISurfaceComposer.h> -#include <ui/DisplayInfo.h> - -// --------------------------------------------------------------------------- - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// --------------------------------------------------------------------------- - -namespace android { - -class BpSurfaceComposer : public BpInterface<ISurfaceComposer> -{ -public: - BpSurfaceComposer(const sp<IBinder>& impl) - : BpInterface<ISurfaceComposer>(impl) - { - } - - virtual sp<ISurfaceFlingerClient> createConnection() - { - uint32_t n; - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply); - return interface_cast<ISurfaceFlingerClient>(reply.readStrongBinder()); - } - - virtual sp<IMemory> getCblk() const - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::GET_CBLK, data, &reply); - return interface_cast<IMemory>(reply.readStrongBinder()); - } - - virtual void openGlobalTransaction() - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::OPEN_GLOBAL_TRANSACTION, data, &reply); - } - - virtual void closeGlobalTransaction() - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::CLOSE_GLOBAL_TRANSACTION, data, &reply); - } - - virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeInt32(dpy); - data.writeInt32(flags); - remote()->transact(BnSurfaceComposer::FREEZE_DISPLAY, data, &reply); - return reply.readInt32(); - } - - virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeInt32(dpy); - data.writeInt32(flags); - remote()->transact(BnSurfaceComposer::UNFREEZE_DISPLAY, data, &reply); - return reply.readInt32(); - } - - virtual int setOrientation(DisplayID dpy, int orientation) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeInt32(dpy); - data.writeInt32(orientation); - remote()->transact(BnSurfaceComposer::SET_ORIENTATION, data, &reply); - return reply.readInt32(); - } - - virtual void bootFinished() - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); - } - - virtual status_t requestGPU( - const sp<IGPUCallback>& callback, gpu_info_t* gpu) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(callback->asBinder()); - remote()->transact(BnSurfaceComposer::REQUEST_GPU, data, &reply); - gpu->regs = interface_cast<IMemory>(reply.readStrongBinder()); - gpu->count = reply.readInt32(); - - // FIXME: for now, we don't dynamically allocate the regions array - size_t maxCount = sizeof(gpu->regions)/sizeof(*gpu->regions); - if (gpu->count > maxCount) - return BAD_VALUE; - - for (size_t i=0 ; i<gpu->count ; i++) { - gpu->regions[i].region = interface_cast<IMemory>(reply.readStrongBinder()); - gpu->regions[i].reserved = reply.readInt32(); - } - return reply.readInt32(); - } - - virtual status_t revokeGPU() - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::REVOKE_GPU, data, &reply); - return reply.readInt32(); - } - - virtual void signal() const - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnSurfaceComposer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - status_t err = BnInterface<ISurfaceComposer>::onTransact(code, data, reply, flags); - if (err == NO_ERROR) - return err; - - CHECK_INTERFACE(ISurfaceComposer, data, reply); - - switch(code) { - case CREATE_CONNECTION: { - sp<IBinder> b = createConnection()->asBinder(); - reply->writeStrongBinder(b); - } break; - case OPEN_GLOBAL_TRANSACTION: { - openGlobalTransaction(); - } break; - case CLOSE_GLOBAL_TRANSACTION: { - closeGlobalTransaction(); - } break; - case SET_ORIENTATION: { - DisplayID dpy = data.readInt32(); - int orientation = data.readInt32(); - reply->writeInt32( setOrientation(dpy, orientation) ); - } break; - case FREEZE_DISPLAY: { - DisplayID dpy = data.readInt32(); - uint32_t flags = data.readInt32(); - reply->writeInt32( freezeDisplay(dpy, flags) ); - } break; - case UNFREEZE_DISPLAY: { - DisplayID dpy = data.readInt32(); - uint32_t flags = data.readInt32(); - reply->writeInt32( unfreezeDisplay(dpy, flags) ); - } break; - case BOOT_FINISHED: { - bootFinished(); - } break; - case REVOKE_GPU: { - reply->writeInt32( revokeGPU() ); - } break; - case SIGNAL: { - signal(); - } break; - case GET_CBLK: { - sp<IBinder> b = getCblk()->asBinder(); - reply->writeStrongBinder(b); - } break; - case REQUEST_GPU: { - // TODO: this should be protected by a permission - gpu_info_t info; - sp<IGPUCallback> callback - = interface_cast<IGPUCallback>(data.readStrongBinder()); - status_t res = requestGPU(callback, &info); - - // FIXME: for now, we don't dynamically allocate the regions array - size_t maxCount = sizeof(info.regions)/sizeof(*info.regions); - if (info.count > maxCount) - return BAD_VALUE; - - reply->writeStrongBinder(info.regs->asBinder()); - reply->writeInt32(info.count); - for (size_t i=0 ; i<info.count ; i++) { - reply->writeStrongBinder(info.regions[i].region->asBinder()); - reply->writeInt32(info.regions[i].reserved); - } - reply->writeInt32(res); - } break; - default: - return UNKNOWN_TRANSACTION; - } - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -enum { - // Note: BOOT_FINISHED must remain this value, it is called by ActivityManagerService. - GPU_LOST = IBinder::FIRST_CALL_TRANSACTION -}; - -class BpGPUCallback : public BpInterface<IGPUCallback> -{ -public: - BpGPUCallback(const sp<IBinder>& impl) - : BpInterface<IGPUCallback>(impl) - { - } - - virtual void gpuLost() - { - Parcel data, reply; - data.writeInterfaceToken(IGPUCallback::getInterfaceDescriptor()); - remote()->transact(GPU_LOST, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(GPUCallback, "android.ui.IGPUCallback"); - -status_t BnGPUCallback::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GPU_LOST: { - CHECK_INTERFACE(IGPUCallback, data, reply); - gpuLost(); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp deleted file mode 100644 index dd6a798..0000000 --- a/libs/ui/ISurfaceFlingerClient.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// tag as surfaceflinger -#define LOG_TAG "SurfaceFlinger" - -#include <stdio.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Parcel.h> -#include <utils/IMemory.h> -#include <utils/IPCThreadState.h> -#include <utils/IServiceManager.h> - -#include <ui/ISurface.h> -#include <ui/ISurfaceFlingerClient.h> -#include <ui/Point.h> -#include <ui/Rect.h> - -#include <private/ui/LayerState.h> - -// --------------------------------------------------------------------------- - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// --------------------------------------------------------------------------- - -namespace android { - -enum { - GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, - CREATE_SURFACE, - DESTROY_SURFACE, - SET_STATE -}; - -class BpSurfaceFlingerClient : public BpInterface<ISurfaceFlingerClient> -{ -public: - BpSurfaceFlingerClient(const sp<IBinder>& impl) - : BpInterface<ISurfaceFlingerClient>(impl) - { - } - - virtual void getControlBlocks(sp<IMemory>* ctl) const - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor()); - remote()->transact(GET_CBLK, data, &reply); - *ctl = interface_cast<IMemory>(reply.readStrongBinder()); - } - - virtual sp<ISurface> createSurface( surface_data_t* params, - int pid, - DisplayID display, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor()); - data.writeInt32(pid); - data.writeInt32(display); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - data.writeInt32(flags); - remote()->transact(CREATE_SURFACE, data, &reply); - params->readFromParcel(reply); - return interface_cast<ISurface>(reply.readStrongBinder()); - } - - virtual status_t destroySurface(SurfaceID sid) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor()); - data.writeInt32(sid); - remote()->transact(DESTROY_SURFACE, data, &reply); - return reply.readInt32(); - } - - virtual status_t setState(int32_t count, const layer_state_t* states) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor()); - data.writeInt32(count); - for (int i=0 ; i<count ; i++) - states[i].write(data); - remote()->transact(SET_STATE, data, &reply); - return reply.readInt32(); - } -}; - -IMPLEMENT_META_INTERFACE(SurfaceFlingerClient, "android.ui.ISurfaceFlingerClient"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnSurfaceFlingerClient::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - // codes that don't require permission check - - switch(code) { - case GET_CBLK: { - CHECK_INTERFACE(ISurfaceFlingerClient, data, reply); - sp<IMemory> ctl; - getControlBlocks(&ctl); - reply->writeStrongBinder(ctl->asBinder()); - return NO_ERROR; - } break; - } - - // these must be checked - - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int self_pid = getpid(); - if (UNLIKELY(pid != self_pid)) { - // we're called from a different process, do the real check - if (!checkCallingPermission( - String16("android.permission.ACCESS_SURFACE_FLINGER"))) - { - const int uid = ipc->getCallingUid(); - LOGE("Permission Denial: " - "can't openGlobalTransaction pid=%d, uid=%d", pid, uid); - return PERMISSION_DENIED; - } - } - - switch(code) { - case CREATE_SURFACE: { - CHECK_INTERFACE(ISurfaceFlingerClient, data, reply); - surface_data_t params; - int32_t pid = data.readInt32(); - DisplayID display = data.readInt32(); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - PixelFormat format = data.readInt32(); - uint32_t flags = data.readInt32(); - sp<ISurface> s = createSurface(¶ms, pid, display, w, h, format, flags); - params.writeToParcel(reply); - reply->writeStrongBinder(s->asBinder()); - return NO_ERROR; - } break; - case DESTROY_SURFACE: { - CHECK_INTERFACE(ISurfaceFlingerClient, data, reply); - reply->writeInt32( destroySurface( data.readInt32() ) ); - return NO_ERROR; - } break; - case SET_STATE: { - CHECK_INTERFACE(ISurfaceFlingerClient, data, reply); - int32_t count = data.readInt32(); - layer_state_t* states = new layer_state_t[count]; - for (int i=0 ; i<count ; i++) - states[i].read(data); - status_t err = setState(count, states); - delete [] states; - reply->writeInt32(err); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------- - -status_t ISurfaceFlingerClient::surface_data_t::readFromParcel(const Parcel& parcel) -{ - token = parcel.readInt32(); - identity = parcel.readInt32(); - heap[0] = interface_cast<IMemoryHeap>(parcel.readStrongBinder()); - heap[1] = interface_cast<IMemoryHeap>(parcel.readStrongBinder()); - return NO_ERROR; -} - -status_t ISurfaceFlingerClient::surface_data_t::writeToParcel(Parcel* parcel) const -{ - parcel->writeInt32(token); - parcel->writeInt32(identity); - parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL); - parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL); - return NO_ERROR; -} - -}; // namespace android diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp deleted file mode 100644 index e891181..0000000 --- a/libs/ui/KeyCharacterMap.cpp +++ /dev/null @@ -1,263 +0,0 @@ -#define LOG_TAG "KeyCharacterMap" - -#include <ui/KeyCharacterMap.h> -#include <cutils/properties.h> - -#include <utils/Log.h> -#include <sys/types.h> -#include <unistd.h> -#include <stdlib.h> -#include <fcntl.h> -#include <limits.h> -#include <string.h> - -struct Header -{ - char magic[8]; - unsigned int endian; - unsigned int version; - unsigned int keycount; - unsigned char kbdtype; - char padding[11]; -}; - -KeyCharacterMap::KeyCharacterMap() -{ -} - -KeyCharacterMap::~KeyCharacterMap() -{ - free(m_keys); -} - -unsigned short -KeyCharacterMap::get(int keycode, int meta) -{ - Key* k = find_key(keycode); - if (k != NULL) { - return k->data[meta & META_MASK]; - } - return 0; -} - -unsigned short -KeyCharacterMap::getNumber(int keycode) -{ - Key* k = find_key(keycode); - if (k != NULL) { - return k->number; - } - return 0; -} - -unsigned short -KeyCharacterMap::getMatch(int keycode, const unsigned short* chars, - int charsize, uint32_t modifiers) -{ - Key* k = find_key(keycode); - modifiers &= 3; // ignore the SYM key because we don't have keymap entries for it - if (k != NULL) { - const uint16_t* data = k->data; - for (int j=0; j<charsize; j++) { - uint16_t c = chars[j]; - for (int i=0; i<(META_MASK + 1); i++) { - if ((modifiers == 0) || ((modifiers & i) != 0)) { - if (c == data[i]) { - return c; - } - } - } - } - } - return 0; -} - -unsigned short -KeyCharacterMap::getDisplayLabel(int keycode) -{ - Key* k = find_key(keycode); - if (k != NULL) { - return k->display_label; - } - return 0; -} - -bool -KeyCharacterMap::getKeyData(int keycode, unsigned short *displayLabel, - unsigned short *number, unsigned short* results) -{ - Key* k = find_key(keycode); - if (k != NULL) { - memcpy(results, k->data, sizeof(short)*(META_MASK + 1)); - *number = k->number; - *displayLabel = k->display_label; - return true; - } else { - return false; - } -} - -bool -KeyCharacterMap::find_char(uint16_t c, uint32_t* key, uint32_t* mods) -{ - uint32_t N = m_keyCount; - for (int j=0; j<(META_MASK + 1); j++) { - Key const* keys = m_keys; - for (uint32_t i=0; i<N; i++) { - if (keys->data[j] == c) { - *key = keys->keycode; - *mods = j; - return true; - } - keys++; - } - } - return false; -} - -bool -KeyCharacterMap::getEvents(uint16_t* chars, size_t len, - Vector<int32_t>* keys, Vector<uint32_t>* modifiers) -{ - for (size_t i=0; i<len; i++) { - uint32_t k, mods; - if (find_char(chars[i], &k, &mods)) { - keys->add(k); - modifiers->add(mods); - } else { - return false; - } - } - return true; -} - -KeyCharacterMap::Key* -KeyCharacterMap::find_key(int keycode) -{ - Key* keys = m_keys; - int low = 0; - int high = m_keyCount - 1; - int mid; - int n; - while (low <= high) { - mid = (low + high) / 2; - n = keys[mid].keycode; - if (keycode < n) { - high = mid - 1; - } else if (keycode > n) { - low = mid + 1; - } else { - return keys + mid; - } - } - return NULL; -} - -KeyCharacterMap* -KeyCharacterMap::load(int id) -{ - KeyCharacterMap* rv = NULL; - char path[PATH_MAX]; - char propName[100]; - char dev[PROPERTY_VALUE_MAX]; - char tmpfn[PROPERTY_VALUE_MAX]; - int err; - const char* root = getenv("ANDROID_ROOT"); - - sprintf(propName, "hw.keyboards.%u.devname", id); - err = property_get(propName, dev, ""); - if (err > 0) { - // replace all the spaces with underscores - strcpy(tmpfn, dev); - for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' ')) - *p = '_'; - snprintf(path, sizeof(path), "%s/usr/keychars/%s.kcm.bin", root, tmpfn); - //LOGD("load: dev='%s' path='%s'\n", dev, path); - rv = try_file(path); - if (rv != NULL) { - return rv; - } - LOGW("Error loading keycharmap file '%s'. %s='%s'", path, propName, dev); - } else { - LOGW("No keyboard for id %d", id); - } - - snprintf(path, sizeof(path), "%s/usr/keychars/qwerty.kcm.bin", root); - rv = try_file(path); - if (rv == NULL) { - LOGE("Can't find any keycharmaps (also tried %s)", path); - return NULL; - } - LOGW("Using default keymap: %s", path); - - return rv; -} - -KeyCharacterMap* -KeyCharacterMap::try_file(const char* filename) -{ - KeyCharacterMap* rv = NULL; - Key* keys; - int fd; - off_t filesize; - Header header; - int err; - - fd = open(filename, O_RDONLY); - if (fd == -1) { - LOGW("Can't open keycharmap file"); - return NULL; - } - - filesize = lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); - - // validate the header - if (filesize <= (off_t)sizeof(header)) { - LOGW("Bad keycharmap - filesize=%d\n", (int)filesize); - goto cleanup1; - } - - err = read(fd, &header, sizeof(header)); - if (err == -1) { - LOGW("Error reading keycharmap file"); - goto cleanup1; - } - - if (0 != memcmp(header.magic, "keychar", 8)) { - LOGW("Bad keycharmap magic token"); - goto cleanup1; - } - if (header.endian != 0x12345678) { - LOGW("Bad keycharmap endians"); - goto cleanup1; - } - if ((header.version & 0xff) != 2) { - LOGW("Only support keycharmap version 2 (got 0x%08x)", header.version); - goto cleanup1; - } - if (filesize < (off_t)(sizeof(Header)+(sizeof(Key)*header.keycount))) { - LOGW("Bad keycharmap file size\n"); - goto cleanup1; - } - - // read the key data - keys = (Key*)malloc(sizeof(Key)*header.keycount); - err = read(fd, keys, sizeof(Key)*header.keycount); - if (err == -1) { - LOGW("Error reading keycharmap file"); - free(keys); - goto cleanup1; - } - - // return the object - rv = new KeyCharacterMap; - rv->m_keyCount = header.keycount; - rv->m_keys = keys; - rv->m_type = header.kbdtype; - -cleanup1: - close(fd); - - return rv; -} diff --git a/libs/ui/KeyLayoutMap.cpp b/libs/ui/KeyLayoutMap.cpp deleted file mode 100644 index 15ae54c..0000000 --- a/libs/ui/KeyLayoutMap.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#define LOG_TAG "KeyLayoutMap" - -#include "KeyLayoutMap.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <utils/String8.h> -#include <stdlib.h> -#include <ui/KeycodeLabels.h> -#include <utils/Log.h> - -namespace android { - -KeyLayoutMap::KeyLayoutMap() - :m_status(NO_INIT), - m_keys() -{ -} - -KeyLayoutMap::~KeyLayoutMap() -{ -} - -static String8 -next_token(char const** p, int *line) -{ - bool begun = false; - const char* begin = *p; - const char* end = *p; - while (true) { - if (*end == '\n') { - (*line)++; - } - switch (*end) - { - case '#': - if (begun) { - *p = end; - return String8(begin, end-begin); - } else { - do { - begin++; - end++; - } while (*begin != '\0' && *begin != '\n'); - } - case '\0': - case ' ': - case '\n': - case '\r': - case '\t': - if (begun || (*end == '\0')) { - *p = end; - return String8(begin, end-begin); - } else { - begin++; - end++; - break; - } - default: - end++; - begun = true; - } - } -} - -static int32_t -token_to_value(const char *literal, const KeycodeLabel *list) -{ - while (list->literal) { - if (0 == strcmp(literal, list->literal)) { - return list->value; - } - list++; - } - return list->value; -} - -status_t -KeyLayoutMap::load(const char* filename) -{ - int fd = open(filename, O_RDONLY); - if (fd < 0) { - LOGE("error opening file=%s err=%s\n", filename, strerror(errno)); - m_status = errno; - return errno; - } - - off_t len = lseek(fd, 0, SEEK_END); - off_t errlen = lseek(fd, 0, SEEK_SET); - if (len < 0 || errlen < 0) { - close(fd); - LOGE("error seeking file=%s err=%s\n", filename, strerror(errno)); - m_status = errno; - return errno; - } - - char* buf = (char*)malloc(len+1); - if (read(fd, buf, len) != len) { - LOGE("error reading file=%s err=%s\n", filename, strerror(errno)); - m_status = errno != 0 ? errno : ((int)NOT_ENOUGH_DATA); - return errno != 0 ? errno : ((int)NOT_ENOUGH_DATA); - } - errno = 0; - buf[len] = '\0'; - - int32_t scancode = -1; - int32_t keycode = -1; - uint32_t flags = 0; - uint32_t tmp; - char* end; - status_t err = NO_ERROR; - int line = 1; - char const* p = buf; - enum { BEGIN, SCANCODE, KEYCODE, FLAG } state = BEGIN; - while (true) { - String8 token = next_token(&p, &line); - if (*p == '\0') { - break; - } - switch (state) - { - case BEGIN: - if (token == "key") { - state = SCANCODE; - } else { - LOGE("%s:%d: expected key, got '%s'\n", filename, line, - token.string()); - err = BAD_VALUE; - goto done; - } - break; - case SCANCODE: - scancode = strtol(token.string(), &end, 0); - if (*end != '\0') { - LOGE("%s:%d: expected scancode (a number), got '%s'\n", - filename, line, token.string()); - goto done; - } - //LOGI("%s:%d: got scancode %d\n", filename, line, scancode ); - state = KEYCODE; - break; - case KEYCODE: - keycode = token_to_value(token.string(), KEYCODES); - //LOGI("%s:%d: got keycode %d for %s\n", filename, line, keycode, token.string() ); - if (keycode == 0) { - LOGE("%s:%d: expected keycode, got '%s'\n", - filename, line, token.string()); - goto done; - } - state = FLAG; - break; - case FLAG: - if (token == "key") { - if (scancode != -1) { - //LOGI("got key decl scancode=%d keycode=%d" - // " flags=0x%08x\n", scancode, keycode, flags); - Key k = { keycode, flags }; - m_keys.add(scancode, k); - state = SCANCODE; - scancode = -1; - keycode = -1; - flags = 0; - break; - } - } - tmp = token_to_value(token.string(), FLAGS); - //LOGI("%s:%d: got flags %x for %s\n", filename, line, tmp, token.string() ); - if (tmp == 0) { - LOGE("%s:%d: expected flag, got '%s'\n", - filename, line, token.string()); - goto done; - } - flags |= tmp; - break; - } - } - if (state == FLAG && scancode != -1 ) { - //LOGI("got key decl scancode=%d keycode=%d" - // " flags=0x%08x\n", scancode, keycode, flags); - Key k = { keycode, flags }; - m_keys.add(scancode, k); - } - -done: - free(buf); - close(fd); - - m_status = err; - return err; -} - -status_t -KeyLayoutMap::map(int32_t scancode, int32_t *keycode, uint32_t *flags) const -{ - if (m_status != NO_ERROR) { - return m_status; - } - - ssize_t index = m_keys.indexOfKey(scancode); - if (index < 0) { - //LOGW("couldn't map scancode=%d\n", scancode); - return NAME_NOT_FOUND; - } - - const Key& k = m_keys.valueAt(index); - - *keycode = k.keycode; - *flags = k.flags; - - //LOGD("mapped scancode=%d to keycode=%d flags=0x%08x\n", scancode, - // keycode, flags); - - return NO_ERROR; -} - -status_t -KeyLayoutMap::findScancodes(int32_t keycode, Vector<int32_t>* outScancodes) const -{ - if (m_status != NO_ERROR) { - return m_status; - } - - const size_t N = m_keys.size(); - for (size_t i=0; i<N; i++) { - if (m_keys.valueAt(i).keycode == keycode) { - outScancodes->add(m_keys.keyAt(i)); - } - } - - return NO_ERROR; -} - -}; diff --git a/libs/ui/KeyLayoutMap.h b/libs/ui/KeyLayoutMap.h deleted file mode 100644 index 43f84ce..0000000 --- a/libs/ui/KeyLayoutMap.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef KEYLAYOUTMAP_H -#define KEYLAYOUTMAP_H - -#include <utils/KeyedVector.h> - -namespace android { - -class KeyLayoutMap -{ -public: - KeyLayoutMap(); - ~KeyLayoutMap(); - - status_t load(const char* filename); - - status_t map(int32_t scancode, int32_t *keycode, uint32_t *flags) const; - status_t findScancodes(int32_t keycode, Vector<int32_t>* outScancodes) const; - -private: - struct Key { - int32_t keycode; - uint32_t flags; - }; - - status_t m_status; - KeyedVector<int32_t,Key> m_keys; -}; - -}; - -#endif // KEYLAYOUTMAP_H diff --git a/libs/ui/LayerState.cpp b/libs/ui/LayerState.cpp deleted file mode 100644 index 0b6374b..0000000 --- a/libs/ui/LayerState.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/Errors.h> -#include <utils/Parcel.h> -#include <private/ui/LayerState.h> - -namespace android { - -status_t layer_state_t::write(Parcel& output) const -{ - size_t size = sizeof(layer_state_t); - - //output.writeStrongBinder(surface->asBinder()); - //size -= sizeof(surface); - - transparentRegion.write(output); - size -= sizeof(transparentRegion); - - output.write(this, size); - - return NO_ERROR; -} - -status_t layer_state_t::read(const Parcel& input) -{ - size_t size = sizeof(layer_state_t); - - //surface = interface_cast<ISurface>(input.readStrongBinder()); - //size -= sizeof(surface); - - transparentRegion.read(input); - size -= sizeof(transparentRegion); - - input.read(this, size); - - return NO_ERROR; -} - -}; // namespace android diff --git a/libs/ui/MODULE_LICENSE_APACHE2 b/libs/ui/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/libs/ui/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/libs/ui/NOTICE b/libs/ui/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/libs/ui/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp deleted file mode 100644 index b236edc..0000000 --- a/libs/ui/Overlay.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/IMemory.h> -#include <utils/Parcel.h> -#include <utils/Errors.h> -#include <utils/MemoryHeapBase.h> - -#include <ui/IOverlay.h> -#include <ui/Overlay.h> - -#include <hardware/overlay.h> - -namespace android { - -Overlay::Overlay(const sp<OverlayRef>& overlayRef) - : mOverlayRef(overlayRef), mOverlayData(0), mStatus(NO_INIT) -{ - mOverlayData = NULL; - hw_module_t const* module; - if (overlayRef != 0) { - if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { - if (overlay_data_open(module, &mOverlayData) == NO_ERROR) { - mStatus = mOverlayData->initialize(mOverlayData, - overlayRef->mOverlayHandle); - } - } - } -} - -Overlay::~Overlay() { - if (mOverlayData) { - overlay_data_close(mOverlayData); - } -} - -status_t Overlay::dequeueBuffer(overlay_buffer_t* buffer) -{ - if (mStatus != NO_ERROR) return mStatus; - return mOverlayData->dequeueBuffer(mOverlayData, buffer); -} - -status_t Overlay::queueBuffer(overlay_buffer_t buffer) -{ - if (mStatus != NO_ERROR) return mStatus; - return mOverlayData->queueBuffer(mOverlayData, buffer); -} - -int32_t Overlay::getBufferCount() const -{ - if (mStatus != NO_ERROR) return mStatus; - return mOverlayData->getBufferCount(mOverlayData); -} - -void* Overlay::getBufferAddress(overlay_buffer_t buffer) -{ - if (mStatus != NO_ERROR) return NULL; - return mOverlayData->getBufferAddress(mOverlayData, buffer); -} - -void Overlay::destroy() { - if (mStatus != NO_ERROR) return; - mOverlayRef->mOverlayChannel->destroy(); -} - -status_t Overlay::getStatus() const { - return mStatus; -} - -overlay_handle_t Overlay::getHandleRef() const { - if (mStatus != NO_ERROR) return NULL; - return mOverlayRef->mOverlayHandle; -} - -uint32_t Overlay::getWidth() const { - if (mStatus != NO_ERROR) return 0; - return mOverlayRef->mWidth; -} - -uint32_t Overlay::getHeight() const { - if (mStatus != NO_ERROR) return 0; - return mOverlayRef->mHeight; -} - -int32_t Overlay::getFormat() const { - if (mStatus != NO_ERROR) return -1; - return mOverlayRef->mFormat; -} - -int32_t Overlay::getWidthStride() const { - if (mStatus != NO_ERROR) return 0; - return mOverlayRef->mWidthStride; -} - -int32_t Overlay::getHeightStride() const { - if (mStatus != NO_ERROR) return 0; - return mOverlayRef->mHeightStride; -} -// ---------------------------------------------------------------------------- - -OverlayRef::OverlayRef() - : mOverlayHandle(0), - mWidth(0), mHeight(0), mFormat(0), mWidthStride(0), mHeightStride(0), - mOwnHandle(true) -{ -} - -OverlayRef::OverlayRef(overlay_handle_t handle, const sp<IOverlay>& channel, - uint32_t w, uint32_t h, int32_t f, uint32_t ws, uint32_t hs) - : mOverlayHandle(handle), mOverlayChannel(channel), - mWidth(w), mHeight(h), mFormat(f), mWidthStride(ws), mHeightStride(hs), - mOwnHandle(false) -{ -} - -OverlayRef::~OverlayRef() -{ - if (mOwnHandle) { - /* FIXME: handles should be promoted to "real" API and be handled by - * the framework */ - for (int i=0 ; i<mOverlayHandle->numFds ; i++) { - close(mOverlayHandle->data[i]); - } - free((void*)mOverlayHandle); - } -} - -sp<OverlayRef> OverlayRef::readFromParcel(const Parcel& data) { - sp<OverlayRef> result; - sp<IOverlay> overlay = IOverlay::asInterface(data.readStrongBinder()); - if (overlay != NULL) { - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - uint32_t f = data.readInt32(); - uint32_t ws = data.readInt32(); - uint32_t hs = data.readInt32(); - native_handle* handle = data.readNativeHandle(NULL, NULL); - - result = new OverlayRef(); - result->mOverlayHandle = handle; - result->mOverlayChannel = overlay; - result->mWidth = w; - result->mHeight = h; - result->mFormat = f; - result->mWidthStride = ws; - result->mHeightStride = hs; - } - return result; -} - -status_t OverlayRef::writeToParcel(Parcel* reply, const sp<OverlayRef>& o) { - if (o != NULL) { - reply->writeStrongBinder(o->mOverlayChannel->asBinder()); - reply->writeInt32(o->mWidth); - reply->writeInt32(o->mHeight); - reply->writeInt32(o->mFormat); - reply->writeInt32(o->mWidthStride); - reply->writeInt32(o->mHeightStride); - reply->writeNativeHandle(*(o->mOverlayHandle)); - } else { - reply->writeStrongBinder(NULL); - } - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp deleted file mode 100644 index b65ed97..0000000 --- a/libs/ui/PixelFormat.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <ui/PixelFormat.h> -#include <pixelflinger/format.h> - -namespace android { - -size_t PixelFormatInfo::getScanlineSize(unsigned int width) const -{ - size_t size; - if ((components >= 6) && (components <= 8)) { - // YCbCr formats are differents. - size = (width * bitsPerPixel)>>3; - } else { - size = width * bytesPerPixel; - } - return size; -} - -ssize_t bytesPerPixel(PixelFormat format) -{ - PixelFormatInfo info; - status_t err = getPixelFormatInfo(format, &info); - return (err < 0) ? err : info.bytesPerPixel; -} - -ssize_t bitsPerPixel(PixelFormat format) -{ - PixelFormatInfo info; - status_t err = getPixelFormatInfo(format, &info); - return (err < 0) ? err : info.bitsPerPixel; -} - -status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info) -{ - if (format < 0) - return BAD_VALUE; - - if (info->version != sizeof(PixelFormatInfo)) - return INVALID_OPERATION; - - size_t numEntries; - const GGLFormat *i = gglGetPixelFormatTable(&numEntries) + format; - bool valid = uint32_t(format) < numEntries; - if (!valid) { - return BAD_INDEX; - } - - #define COMPONENT(name) \ - case GGL_##name: info->components = PixelFormatInfo::name; break; - - switch (i->components) { - COMPONENT(ALPHA) - COMPONENT(RGB) - COMPONENT(RGBA) - COMPONENT(LUMINANCE) - COMPONENT(LUMINANCE_ALPHA) - COMPONENT(Y_CB_CR_SP) - COMPONENT(Y_CB_CR_P) - COMPONENT(Y_CB_CR_I) - default: - return BAD_INDEX; - } - - #undef COMPONENT - - info->format = format; - info->bytesPerPixel = i->size; - info->bitsPerPixel = i->bitsPerPixel; - info->h_alpha = i->ah; - info->l_alpha = i->al; - info->h_red = i->rh; - info->l_red = i->rl; - info->h_green = i->gh; - info->l_green = i->gl; - info->h_blue = i->bh; - info->l_blue = i->bl; - - return NO_ERROR; -} - -}; // namespace android - diff --git a/libs/ui/Point.cpp b/libs/ui/Point.cpp deleted file mode 100644 index 438d49f..0000000 --- a/libs/ui/Point.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Point.cpp - * Android - * - * Created on 11/16/2006. - * Copyright 2005 The Android Open Source Project - * - */ - -#include <ui/Point.h> - diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp deleted file mode 100644 index 99e68bb..0000000 --- a/libs/ui/Rect.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Rect.cpp - * Android - * - * Created on 10/14/05. - * Copyright 2005 The Android Open Source Project - * - */ - -#include <ui/Rect.h> - -namespace android { - -inline int min(int a, int b) { - return (a<b) ? a : b; -} - -inline int max(int a, int b) { - return (a>b) ? a : b; -} - -void Rect::makeInvalid() { - left = 0; - top = 0; - right = -1; - bottom = -1; -} - -bool Rect::operator < (const Rect& rhs) const -{ - if (top<rhs.top) { - return true; - } else if (top == rhs.top) { - if (left < rhs.left) { - return true; - } else if (left == rhs.left) { - if (bottom<rhs.bottom) { - return true; - } else if (bottom == rhs.bottom) { - if (right<rhs.right) { - return true; - } - } - } - } - return false; -} - -Rect& Rect::offsetTo(int x, int y) -{ - right -= left - x; - bottom -= top - y; - left = x; - top = y; - return *this; -} - -Rect& Rect::offsetBy(int x, int y) -{ - left += x; - top += y; - right+= x; - bottom+=y; - return *this; -} - -Rect Rect::operator + (const Point& rhs) const -{ - return Rect(left+rhs.x, top+rhs.y, right+rhs.x, bottom+rhs.y); -} - -Rect Rect::operator - (const Point& rhs) const -{ - return Rect(left-rhs.x, top-rhs.y, right-rhs.x, bottom-rhs.y); -} - -bool Rect::intersect(const Rect& with, Rect* result) const -{ - result->left = max(left, with.left); - result->top = max(top, with.top); - result->right = min(right, with.right); - result->bottom = min(bottom, with.bottom); - return !(result->isEmpty()); -} - -}; // namespace android diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp deleted file mode 100644 index 26e694a..0000000 --- a/libs/ui/Region.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Region" - -#include <stdio.h> -#include <utils/Atomic.h> -#include <utils/Debug.h> -#include <utils/String8.h> -#include <ui/Region.h> - -namespace android { - -// ---------------------------------------------------------------------------- - -Region::Region() -{ -} - -Region::Region(const Region& rhs) - : mRegion(rhs.mRegion) -{ -} - -Region::Region(const SkRegion& rhs) - : mRegion(rhs) -{ -} - -Region::~Region() -{ -} - -Region::Region(const Rect& rhs) -{ - set(rhs); -} - -Region::Region(const Parcel& parcel) -{ - read(parcel); -} - -Region::Region(const void* buffer) -{ - read(buffer); -} - -Region& Region::operator = (const Region& rhs) -{ - mRegion = rhs.mRegion; - return *this; -} - -const SkRegion& Region::toSkRegion() const -{ - return mRegion; -} - -Rect Region::bounds() const -{ - const SkIRect& b(mRegion.getBounds()); - return Rect(b.fLeft, b.fTop, b.fRight, b.fBottom); -} - -void Region::clear() -{ - mRegion.setEmpty(); -} - -void Region::set(const Rect& r) -{ - SkIRect ir; - ir.set(r.left, r.top, r.right, r.bottom); - mRegion.setRect(ir); -} - -// ---------------------------------------------------------------------------- - -Region& Region::orSelf(const Rect& r) -{ - SkIRect ir; - ir.set(r.left, r.top, r.right, r.bottom); - mRegion.op(ir, SkRegion::kUnion_Op); - return *this; -} - -Region& Region::andSelf(const Rect& r) -{ - SkIRect ir; - ir.set(r.left, r.top, r.right, r.bottom); - mRegion.op(ir, SkRegion::kIntersect_Op); - return *this; -} - -// ---------------------------------------------------------------------------- - -Region& Region::orSelf(const Region& rhs) { - mRegion.op(rhs.mRegion, SkRegion::kUnion_Op); - return *this; -} - -Region& Region::andSelf(const Region& rhs) { - mRegion.op(rhs.mRegion, SkRegion::kIntersect_Op); - return *this; -} - -Region& Region::subtractSelf(const Region& rhs) { - mRegion.op(rhs.mRegion, SkRegion::kDifference_Op); - return *this; -} - -Region& Region::translateSelf(int x, int y) { - if (x|y) mRegion.translate(x, y); - return *this; -} - -Region Region::merge(const Region& rhs) const { - Region result; - result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kUnion_Op); - return result; -} - -Region Region::intersect(const Region& rhs) const { - Region result; - result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kIntersect_Op); - return result; -} - -Region Region::subtract(const Region& rhs) const { - Region result; - result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kDifference_Op); - return result; -} - -Region Region::translate(int x, int y) const { - Region result; - mRegion.translate(x, y, &result.mRegion); - return result; -} - -// ---------------------------------------------------------------------------- - -Region& Region::orSelf(const Region& rhs, int dx, int dy) { - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - mRegion.op(r, SkRegion::kUnion_Op); - return *this; -} - -Region& Region::andSelf(const Region& rhs, int dx, int dy) { - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - mRegion.op(r, SkRegion::kIntersect_Op); - return *this; -} - -Region& Region::subtractSelf(const Region& rhs, int dx, int dy) { - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - mRegion.op(r, SkRegion::kDifference_Op); - return *this; -} - -Region Region::merge(const Region& rhs, int dx, int dy) const { - Region result; - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - result.mRegion.op(mRegion, r, SkRegion::kUnion_Op); - return result; -} - -Region Region::intersect(const Region& rhs, int dx, int dy) const { - Region result; - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - result.mRegion.op(mRegion, r, SkRegion::kIntersect_Op); - return result; -} - -Region Region::subtract(const Region& rhs, int dx, int dy) const { - Region result; - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - result.mRegion.op(mRegion, r, SkRegion::kDifference_Op); - return result; -} - -// ---------------------------------------------------------------------------- - -Region::iterator::iterator(const Region& r) - : mIt(r.mRegion) -{ -} - -int Region::iterator::iterate(Rect* rect) -{ - if (mIt.done()) - return 0; - const SkIRect& r(mIt.rect()); - rect->left = r.fLeft; - rect->top = r.fTop; - rect->right = r.fRight; - rect->bottom= r.fBottom; - mIt.next(); - return 1; -} - -// ---------------------------------------------------------------------------- - -// we write a 4byte size ahead of the actual region, so we know how much we'll need for reading - -status_t Region::write(Parcel& parcel) const -{ - int32_t size = mRegion.flatten(NULL); - parcel.writeInt32(size); - mRegion.flatten(parcel.writeInplace(size)); - return NO_ERROR; -} - -status_t Region::read(const Parcel& parcel) -{ - size_t size = parcel.readInt32(); - mRegion.unflatten(parcel.readInplace(size)); - return NO_ERROR; -} - -ssize_t Region::write(void* buffer, size_t size) const -{ - size_t sizeNeeded = mRegion.flatten(NULL); - if (sizeNeeded > size) return NO_MEMORY; - return mRegion.flatten(buffer); -} - -ssize_t Region::read(const void* buffer) -{ - return mRegion.unflatten(buffer); -} - -ssize_t Region::writeEmpty(void* buffer, size_t size) -{ - if (size < 4) return NO_MEMORY; - // this needs to stay in sync with SkRegion - *static_cast<int32_t*>(buffer) = -1; - return 4; -} - -bool Region::isEmpty(void* buffer) -{ - // this needs to stay in sync with SkRegion - return *static_cast<int32_t*>(buffer) == -1; -} - -size_t Region::rects(Vector<Rect>& rectList) const -{ - rectList.clear(); - if (!isEmpty()) { - SkRegion::Iterator iterator(mRegion); - while( !iterator.done() ) { - const SkIRect& ir(iterator.rect()); - rectList.push(Rect(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom)); - iterator.next(); - } - } - return rectList.size(); -} - -void Region::dump(String8& out, const char* what, uint32_t flags) const -{ - (void)flags; - Vector<Rect> r; - rects(r); - - size_t SIZE = 256; - char buffer[SIZE]; - - snprintf(buffer, SIZE, " Region %s (this=%p, count=%d)\n", what, this, r.size()); - out.append(buffer); - for (size_t i=0 ; i<r.size() ; i++) { - snprintf(buffer, SIZE, " [%3d, %3d, %3d, %3d]\n", - r[i].left, r[i].top,r[i].right,r[i].bottom); - out.append(buffer); - } -} - -void Region::dump(const char* what, uint32_t flags) const -{ - (void)flags; - Vector<Rect> r; - rects(r); - LOGD(" Region %s (this=%p, count=%d)\n", what, this, r.size()); - for (size_t i=0 ; i<r.size() ; i++) { - LOGD(" [%3d, %3d, %3d, %3d]\n", - r[i].left, r[i].top,r[i].right,r[i].bottom); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp deleted file mode 100644 index 4ea9ae2..0000000 --- a/libs/ui/Surface.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Surface" - -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/threads.h> -#include <utils/IPCThreadState.h> -#include <utils/IMemory.h> -#include <utils/Log.h> - -#include <ui/ISurface.h> -#include <ui/Surface.h> -#include <ui/SurfaceComposerClient.h> -#include <ui/Rect.h> - -#include <private/ui/SharedState.h> -#include <private/ui/LayerState.h> - -namespace android { - -// --------------------------------------------------------------------------- - -Surface::Surface(const sp<SurfaceComposerClient>& client, - const sp<ISurface>& surface, - const ISurfaceFlingerClient::surface_data_t& data, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - bool owner) - : mClient(client), mSurface(surface), - mToken(data.token), mIdentity(data.identity), - mFormat(format), mFlags(flags), mOwner(owner) -{ - mSwapRectangle.makeInvalid(); - mSurfaceHeapBase[0] = 0; - mSurfaceHeapBase[1] = 0; - mHeap[0] = data.heap[0]; - mHeap[1] = data.heap[1]; -} - -Surface::Surface(Surface const* rhs) - : mOwner(false) -{ - mToken = rhs->mToken; - mIdentity= rhs->mIdentity; - mClient = rhs->mClient; - mSurface = rhs->mSurface; - mHeap[0] = rhs->mHeap[0]; - mHeap[1] = rhs->mHeap[1]; - mFormat = rhs->mFormat; - mFlags = rhs->mFlags; - mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0]; - mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1]; - mSwapRectangle.makeInvalid(); -} - -Surface::~Surface() -{ - if (mOwner && mToken>=0 && mClient!=0) { - mClient->destroySurface(mToken); - } - mClient.clear(); - mSurface.clear(); - mHeap[0].clear(); - mHeap[1].clear(); - IPCThreadState::self()->flushCommands(); -} - -sp<Surface> Surface::dup() const -{ - Surface const * r = this; - if (this && mOwner) { - // the only reason we need to do this is because of Java's garbage - // collector: because we're creating a copy of the Surface - // instead of a reference, we can garantee that when our last - // reference goes away, the real surface will be deleted. - // Without this hack (the code is correct too), we'd have to - // wait for a GC for the surface to go away. - r = new Surface(this); - } - return const_cast<Surface*>(r); -} - -status_t Surface::nextBuffer(SurfaceInfo* info) { - return mClient->nextBuffer(this, info); -} - -status_t Surface::lock(SurfaceInfo* info, bool blocking) { - return Surface::lock(info, NULL, blocking); -} - -status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->lockSurface(this, info, dirty, blocking); -} - -status_t Surface::unlockAndPost() { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->unlockAndPostSurface(this); -} - -status_t Surface::unlock() { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->unlockSurface(this); -} - -status_t Surface::setLayer(int32_t layer) { - return mClient->setLayer(this, layer); -} -status_t Surface::setPosition(int32_t x, int32_t y) { - return mClient->setPosition(this, x, y); -} -status_t Surface::setSize(uint32_t w, uint32_t h) { - return mClient->setSize(this, w, h); -} -status_t Surface::hide() { - return mClient->hide(this); -} -status_t Surface::show(int32_t layer) { - return mClient->show(this, layer); -} -status_t Surface::freeze() { - return mClient->freeze(this); -} -status_t Surface::unfreeze() { - return mClient->unfreeze(this); -} -status_t Surface::setFlags(uint32_t flags, uint32_t mask) { - return mClient->setFlags(this, flags, mask); -} -status_t Surface::setTransparentRegionHint(const Region& transparent) { - return mClient->setTransparentRegionHint(this, transparent); -} -status_t Surface::setAlpha(float alpha) { - return mClient->setAlpha(this, alpha); -} -status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy); -} -status_t Surface::setFreezeTint(uint32_t tint) { - return mClient->setFreezeTint(this, tint); -} - -Region Surface::dirtyRegion() const { - return mDirtyRegion; -} -void Surface::setDirtyRegion(const Region& region) const { - mDirtyRegion = region; -} -const Rect& Surface::swapRectangle() const { - return mSwapRectangle; -} -void Surface::setSwapRectangle(const Rect& r) { - mSwapRectangle = r; -} - -sp<Surface> Surface::readFromParcel(Parcel* parcel) -{ - sp<SurfaceComposerClient> client; - ISurfaceFlingerClient::surface_data_t data; - sp<IBinder> clientBinder= parcel->readStrongBinder(); - sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder()); - data.heap[0] = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); - data.heap[1] = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); - data.token = parcel->readInt32(); - data.identity = parcel->readInt32(); - PixelFormat format = parcel->readInt32(); - uint32_t flags = parcel->readInt32(); - - if (clientBinder != NULL) - client = SurfaceComposerClient::clientForConnection(clientBinder); - - return new Surface(client, surface, data, 0, 0, format, flags, false); -} - -status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel) -{ - uint32_t flags=0; - uint32_t format=0; - SurfaceID token = -1; - uint32_t identity = 0; - sp<SurfaceComposerClient> client; - sp<ISurface> sur; - sp<IMemoryHeap> heap[2]; - if (surface->isValid()) { - token = surface->mToken; - identity = surface->mIdentity; - client = surface->mClient; - sur = surface->mSurface; - heap[0] = surface->mHeap[0]; - heap[1] = surface->mHeap[1]; - format = surface->mFormat; - flags = surface->mFlags; - } - parcel->writeStrongBinder(client!=0 ? client->connection() : NULL); - parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); - parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL); - parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL); - parcel->writeInt32(token); - parcel->writeInt32(identity); - parcel->writeInt32(format); - parcel->writeInt32(flags); - return NO_ERROR; -} - -bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) -{ - if (lhs == 0 || rhs == 0) - return false; - return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); -} - -void* Surface::heapBase(int i) const -{ - void* heapBase = mSurfaceHeapBase[i]; - // map lazily so it doesn't get mapped in clients that don't need it - if (heapBase == 0) { - const sp<IMemoryHeap>& heap(mHeap[i]); - if (heap != 0) { - heapBase = static_cast<uint8_t*>(heap->base()); - if (heapBase == MAP_FAILED) { - heapBase = NULL; - LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)", - heap->asBinder().get(), heap.get()); - } - mSurfaceHeapBase[i] = heapBase; - } - } - return heapBase; -} - -}; // namespace android - diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp deleted file mode 100644 index 9354a7a..0000000 --- a/libs/ui/SurfaceComposerClient.cpp +++ /dev/null @@ -1,1026 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceComposerClient" - -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <cutils/memory.h> - -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/threads.h> -#include <utils/KeyedVector.h> -#include <utils/IPCThreadState.h> -#include <utils/IServiceManager.h> -#include <utils/IMemory.h> -#include <utils/Log.h> - -#include <ui/ISurfaceComposer.h> -#include <ui/ISurfaceFlingerClient.h> -#include <ui/ISurface.h> -#include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> -#include <ui/Rect.h> -#include <ui/Point.h> - -#include <private/ui/SharedState.h> -#include <private/ui/LayerState.h> -#include <private/ui/SurfaceFlingerSynchro.h> - -#include <pixelflinger/pixelflinger.h> - -#include <utils/BpBinder.h> - -#define VERBOSE(...) ((void)0) -//#define VERBOSE LOGD - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -namespace android { - -// --------------------------------------------------------------------------- - -// Must not be holding SurfaceComposerClient::mLock when acquiring gLock here. -static Mutex gLock; -static sp<ISurfaceComposer> gSurfaceManager; -static DefaultKeyedVector< sp<IBinder>, sp<SurfaceComposerClient> > gActiveConnections; -static SortedVector<sp<SurfaceComposerClient> > gOpenTransactions; -static sp<IMemory> gServerCblkMemory; -static volatile surface_flinger_cblk_t* gServerCblk; - -const sp<ISurfaceComposer>& _get_surface_manager() -{ - if (gSurfaceManager != 0) { - return gSurfaceManager; - } - - sp<IBinder> binder; - sp<IServiceManager> sm = defaultServiceManager(); - do { - binder = sm->getService(String16("SurfaceFlinger")); - if (binder == 0) { - LOGW("SurfaceFlinger not published, waiting..."); - usleep(500000); // 0.5 s - } - } while(binder == 0); - sp<ISurfaceComposer> sc(interface_cast<ISurfaceComposer>(binder)); - - Mutex::Autolock _l(gLock); - if (gSurfaceManager == 0) { - gSurfaceManager = sc; - } - return gSurfaceManager; -} - -static volatile surface_flinger_cblk_t const * get_cblk() -{ - if (gServerCblk == 0) { - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - Mutex::Autolock _l(gLock); - if (gServerCblk == 0) { - gServerCblkMemory = sm->getCblk(); - LOGE_IF(gServerCblkMemory==0, "Can't get server control block"); - gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->pointer(); - LOGE_IF(gServerCblk==0, "Can't get server control block address"); - } - } - return gServerCblk; -} - -// --------------------------------------------------------------------------- - -static void copyBlt(const GGLSurface& dst, - const GGLSurface& src, const Region& reg) -{ - Region::iterator iterator(reg); - if (iterator) { - // NOTE: dst and src must be the same format - Rect r; - const size_t bpp = bytesPerPixel(src.format); - const size_t dbpr = dst.stride * bpp; - const size_t sbpr = src.stride * bpp; - while (iterator.iterate(&r)) { - ssize_t h = r.bottom - r.top; - if (h) { - size_t size = (r.right - r.left) * bpp; - uint8_t* s = src.data + (r.left + src.stride * r.top) * bpp; - uint8_t* d = dst.data + (r.left + dst.stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); - } - } - } -} - -// --------------------------------------------------------------------------- - -surface_flinger_cblk_t::surface_flinger_cblk_t() -{ -} - -// --------------------------------------------------------------------------- - -per_client_cblk_t::per_client_cblk_t() -{ -} - -// these functions are used by the clients -inline status_t per_client_cblk_t::validate(size_t i) const { - if (uint32_t(i) >= NUM_LAYERS_MAX) - return BAD_INDEX; - if (layers[i].swapState & eInvalidSurface) - return NO_MEMORY; - return NO_ERROR; -} - -int32_t per_client_cblk_t::lock_layer(size_t i, uint32_t flags) -{ - int32_t index; - uint32_t state; - int timeout = 0; - status_t result; - layer_cblk_t * const layer = layers + i; - const bool blocking = flags & BLOCKING; - const bool inspect = flags & INSPECT; - - do { - state = layer->swapState; - - if (UNLIKELY((state&(eFlipRequested|eNextFlipPending)) == eNextFlipPending)) { - LOGE("eNextFlipPending set but eFlipRequested not set, " - "layer=%d (lcblk=%p), state=%08x", - int(i), layer, int(state)); - return INVALID_OPERATION; - } - - if (UNLIKELY(state&eLocked)) { - LOGE("eLocked set when entering lock_layer(), " - "layer=%d (lcblk=%p), state=%08x", - int(i), layer, int(state)); - return WOULD_BLOCK; - } - - - if (state & (eFlipRequested | eNextFlipPending | eResizeRequested - | eInvalidSurface)) - { - int32_t resizeIndex; - Mutex::Autolock _l(lock); - // might block for a very short amount of time - // will never cause the server to block (trylock()) - - goto start_loop_here; - - // We block the client if: - // eNextFlipPending: we've used both buffers already, so we need to - // wait for one to become availlable. - // eResizeRequested: the buffer we're going to acquire is being - // resized. Block until it is done. - // eFlipRequested && eBusy: the buffer we're going to acquire is - // currently in use by the server. - // eInvalidSurface: this is a special case, we don't block in this - // case, we just return an error. - - while((state & (eNextFlipPending|eInvalidSurface)) || - (state & ((resizeIndex) ? eResizeBuffer1 : eResizeBuffer0)) || - ((state & (eFlipRequested|eBusy)) == (eFlipRequested|eBusy)) ) - { - if (state & eInvalidSurface) - return NO_MEMORY; - - if (!blocking) - return WOULD_BLOCK; - - timeout = 0; - result = cv.waitRelative(lock, seconds(1)); - if (__builtin_expect(result!=NO_ERROR, false)) { - const int newState = layer->swapState; - LOGW( "lock_layer timed out (is the CPU pegged?) " - "layer=%d, lcblk=%p, state=%08x (was %08x)", - int(i), layer, newState, int(state)); - timeout = newState != int(state); - } - - start_loop_here: - state = layer->swapState; - resizeIndex = (state&eIndex) ^ ((state&eFlipRequested)>>1); - } - - LOGW_IF(timeout, - "lock_layer() timed out but didn't appear to need " - "to be locked and we recovered " - "(layer=%d, lcblk=%p, state=%08x)", - int(i), layer, int(state)); - } - - // eFlipRequested is not set and cannot be set by another thread: it's - // safe to use the first buffer without synchronization. - - // Choose the index depending on eFlipRequested. - // When it's set, choose the 'other' buffer. - index = (state&eIndex) ^ ((state&eFlipRequested)>>1); - - // make sure this buffer is valid - if (layer->surface[index].bits_offset < 0) { - return status_t(layer->surface[index].bits_offset); - } - - if (inspect) { - // we just want to inspect this layer. don't lock it. - goto done; - } - - // last thing before we're done, we need to atomically lock the state - } while (android_atomic_cmpxchg(state, state|eLocked, &(layer->swapState))); - - VERBOSE("locked layer=%d (lcblk=%p), buffer=%d, state=0x%08x", - int(i), layer, int(index), int(state)); - - // store the index of the locked buffer (for client use only) - layer->flags &= ~eBufferIndex; - layer->flags |= ((index << eBufferIndexShift) & eBufferIndex); - -done: - return index; -} - -uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i) -{ - // atomically set eFlipRequested and clear eLocked and optionnaly - // set eNextFlipPending if eFlipRequested was already set - - layer_cblk_t * const layer = layers + i; - int32_t oldvalue, newvalue; - do { - oldvalue = layer->swapState; - // get current value - - newvalue = oldvalue & ~eLocked; - // clear eLocked - - newvalue |= eFlipRequested; - // set eFlipRequested - - if (oldvalue & eFlipRequested) - newvalue |= eNextFlipPending; - // if eFlipRequested was alread set, set eNextFlipPending - - } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState))); - - VERBOSE("request pageflip for layer=%d, buffer=%d, state=0x%08x", - int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift), - int(newvalue)); - - // from this point, the server can kick in at anytime and use the first - // buffer, so we cannot use it anymore, and we must use the 'other' - // buffer instead (or wait if it is not availlable yet, see lock_layer). - - return newvalue; -} - -void per_client_cblk_t::unlock_layer(size_t i) -{ - layer_cblk_t * const layer = layers + i; - android_atomic_and(~eLocked, &layer->swapState); -} - -// --------------------------------------------------------------------------- - -static inline int compare_type( const layer_state_t& lhs, - const layer_state_t& rhs) { - if (lhs.surface < rhs.surface) return -1; - if (lhs.surface > rhs.surface) return 1; - return 0; -} - -SurfaceComposerClient::SurfaceComposerClient() -{ - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - if (sm == 0) { - _init(0, 0); - return; - } - - _init(sm, sm->createConnection()); - - if (mClient != 0) { - Mutex::Autolock _l(gLock); - VERBOSE("Adding client %p to map", this); - gActiveConnections.add(mClient->asBinder(), this); - } -} - -SurfaceComposerClient::SurfaceComposerClient( - const sp<ISurfaceComposer>& sm, const sp<IBinder>& conn) -{ - _init(sm, interface_cast<ISurfaceFlingerClient>(conn)); -} - -void SurfaceComposerClient::_init( - const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn) -{ - VERBOSE("Creating client %p, conn %p", this, conn.get()); - - mSignalServer = 0; - mPrebuiltLayerState = 0; - mTransactionOpen = 0; - mStatus = NO_ERROR; - mControl = 0; - - mClient = conn; - if (mClient == 0) { - mStatus = NO_INIT; - return; - } - - mClient->getControlBlocks(&mControlMemory); - mSignalServer = new SurfaceFlingerSynchro(sm); - mControl = static_cast<per_client_cblk_t *>(mControlMemory->pointer()); -} - -SurfaceComposerClient::~SurfaceComposerClient() -{ - VERBOSE("Destroying client %p, conn %p", this, mClient.get()); - dispose(); -} - -status_t SurfaceComposerClient::initCheck() const -{ - return mStatus; -} - -status_t SurfaceComposerClient::validateSurface( - per_client_cblk_t const* cblk, Surface const * surface) -{ - SurfaceID index = surface->ID(); - if (cblk == 0) { - LOGE("cblk is null (surface id=%d, identity=%u)", - index, surface->getIdentity()); - return NO_INIT; - } - - status_t err = cblk->validate(index); - if (err != NO_ERROR) { - LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", - index, surface->getIdentity(), err, strerror(-err)); - return err; - } - - if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) { - LOGE("using an invalid surface id=%d, identity=%u should be %d", - index, surface->getIdentity(), cblk->layers[index].identity); - return NO_INIT; - } - - return NO_ERROR; -} - -sp<IBinder> SurfaceComposerClient::connection() const -{ - return (mClient != 0) ? mClient->asBinder() : 0; -} - -sp<SurfaceComposerClient> -SurfaceComposerClient::clientForConnection(const sp<IBinder>& conn) -{ - sp<SurfaceComposerClient> client; - - { // scope for lock - Mutex::Autolock _l(gLock); - client = gActiveConnections.valueFor(conn); - } - - if (client == 0) { - // Need to make a new client. - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - client = new SurfaceComposerClient(sm, conn); - if (client != 0 && client->initCheck() == NO_ERROR) { - Mutex::Autolock _l(gLock); - gActiveConnections.add(conn, client); - //LOGD("we have %d connections", gActiveConnections.size()); - } else { - client.clear(); - } - } - - return client; -} - -void SurfaceComposerClient::dispose() -{ - // this can be called more than once. - - sp<IMemory> controlMemory; - sp<ISurfaceFlingerClient> client; - sp<IMemoryHeap> surfaceHeap; - - { - Mutex::Autolock _lg(gLock); - Mutex::Autolock _lm(mLock); - - delete mSignalServer; - mSignalServer = 0; - - if (mClient != 0) { - client = mClient; - mClient.clear(); - - ssize_t i = gActiveConnections.indexOfKey(client->asBinder()); - if (i >= 0 && gActiveConnections.valueAt(i) == this) { - VERBOSE("Removing client %p from map at %d", this, int(i)); - gActiveConnections.removeItemsAt(i); - } - } - - delete mPrebuiltLayerState; - mPrebuiltLayerState = 0; - controlMemory = mControlMemory; - surfaceHeap = mSurfaceHeap; - mControlMemory.clear(); - mSurfaceHeap.clear(); - mControl = 0; - mStatus = NO_INIT; - } -} - -status_t SurfaceComposerClient::getDisplayInfo( - DisplayID dpy, DisplayInfo* info) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - - info->w = dcblk->w; - info->h = dcblk->h; - info->orientation = dcblk->orientation; - info->xdpi = dcblk->xdpi; - info->ydpi = dcblk->ydpi; - info->fps = dcblk->fps; - info->density = dcblk->density; - return getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo)); -} - -ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->w; -} - -ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->h; -} - -ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->orientation; -} - -ssize_t SurfaceComposerClient::getNumberOfDisplays() -{ - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - uint32_t connected = cblk->connected; - int n = 0; - while (connected) { - if (connected&1) n++; - connected >>= 1; - } - return n; -} - -sp<Surface> SurfaceComposerClient::createSurface( - int pid, - DisplayID display, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags) -{ - sp<Surface> result; - if (mStatus == NO_ERROR) { - ISurfaceFlingerClient::surface_data_t data; - sp<ISurface> surface = mClient->createSurface(&data, pid, - display, w, h, format, flags); - if (surface != 0) { - if (uint32_t(data.token) < NUM_LAYERS_MAX) { - result = new Surface(this, surface, data, w, h, format, flags); - } - } - } - return result; -} - -status_t SurfaceComposerClient::destroySurface(SurfaceID sid) -{ - if (mStatus != NO_ERROR) - return mStatus; - - // it's okay to destroy a surface while a transaction is open, - // (transactions really are a client-side concept) - // however, this indicates probably a misuse of the API or a bug - // in the client code. - LOGW_IF(mTransactionOpen, - "Destroying surface while a transaction is open. " - "Client %p: destroying surface %d, mTransactionOpen=%d", - this, sid, mTransactionOpen); - - status_t err = mClient->destroySurface(sid); - return err; -} - -status_t SurfaceComposerClient::nextBuffer(Surface* surface, - Surface::SurfaceInfo* info) -{ - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - int32_t backIdx = surface->mBackbufferIndex; - layer_cblk_t* const lcblk = &(cblk->layers[index]); - const surface_info_t* const front = lcblk->surface + (1-backIdx); - info->w = front->w; - info->h = front->h; - info->format = front->format; - info->base = surface->heapBase(1-backIdx); - info->bits = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset); - info->bpr = front->bpr; - - return 0; -} - -status_t SurfaceComposerClient::lockSurface( - Surface* surface, - Surface::SurfaceInfo* other, - Region* dirty, - bool blocking) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - int32_t backIdx = cblk->lock_layer(size_t(index), - per_client_cblk_t::BLOCKING); - if (backIdx >= 0) { - surface->mBackbufferIndex = backIdx; - layer_cblk_t* const lcblk = &(cblk->layers[index]); - const surface_info_t* const back = lcblk->surface + backIdx; - const surface_info_t* const front = lcblk->surface + (1-backIdx); - other->w = back->w; - other->h = back->h; - other->format = back->format; - other->base = surface->heapBase(backIdx); - other->bits = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset); - other->bpr = back->bpr; - - const Rect bounds(other->w, other->h); - Region newDirtyRegion; - - if (back->flags & surface_info_t::eBufferDirty) { - /* it is safe to write *back here, because we're guaranteed - * SurfaceFlinger is not touching it (since it just granted - * access to us) */ - const_cast<surface_info_t*>(back)->flags &= - ~surface_info_t::eBufferDirty; - - // content is meaningless in this case and the whole surface - // needs to be redrawn. - - newDirtyRegion.set(bounds); - if (dirty) { - *dirty = newDirtyRegion; - } - - //if (bytesPerPixel(other->format) == 4) { - // android_memset32( - // (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr); - //} else { - // android_memset16( // fill with green - // (uint16_t*)other->bits, 0x7E0, other->h * other->bpr); - //} - } - else - { - if (dirty) { - dirty->andSelf(Region(bounds)); - newDirtyRegion = *dirty; - } else { - newDirtyRegion.set(bounds); - } - - Region copyback; - if (!(lcblk->flags & eNoCopyBack)) { - const Region previousDirtyRegion(surface->dirtyRegion()); - copyback = previousDirtyRegion.subtract(newDirtyRegion); - } - - if (!copyback.isEmpty()) { - // copy front to back - GGLSurface cb; - cb.version = sizeof(GGLSurface); - cb.width = back->w; - cb.height = back->h; - cb.stride = back->stride; - cb.data = (GGLubyte*)surface->heapBase(backIdx); - cb.data += back->bits_offset; - cb.format = back->format; - - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = front->w; - t.height = front->h; - t.stride = front->stride; - t.data = (GGLubyte*)surface->heapBase(1-backIdx); - t.data += front->bits_offset; - t.format = front->format; - - //const Region copyback(lcblk->region + 1-backIdx); - copyBlt(cb, t, copyback); - } - } - - // update dirty region - surface->setDirtyRegion(newDirtyRegion); - } - return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR); -} - -void SurfaceComposerClient::_signal_server() -{ - mSignalServer->signal(); -} - -void SurfaceComposerClient::_send_dirty_region( - layer_cblk_t* lcblk, const Region& dirty) -{ - const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift; - flat_region_t* flat_region = lcblk->region + index; - status_t err = dirty.write(flat_region, sizeof(flat_region_t)); - if (err < NO_ERROR) { - // region doesn't fit, use the bounds - const Region reg(dirty.bounds()); - reg.write(flat_region, sizeof(flat_region_t)); - } -} - -status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - Region dirty(surface->dirtyRegion()); - const Rect& swapRect(surface->swapRectangle()); - if (swapRect.isValid()) { - dirty.set(swapRect); - } - - // transmit the dirty region - layer_cblk_t* const lcblk = &(cblk->layers[index]); - _send_dirty_region(lcblk, dirty); - uint32_t newstate = cblk->unlock_layer_and_post(size_t(index)); - if (!(newstate & eNextFlipPending)) - _signal_server(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::unlockSurface(Surface* surface) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - layer_cblk_t* const lcblk = &(cblk->layers[index]); - cblk->unlock_layer(size_t(index)); - return NO_ERROR; -} - -void SurfaceComposerClient::openGlobalTransaction() -{ - Mutex::Autolock _l(gLock); - - if (gOpenTransactions.size()) { - LOGE("openGlobalTransaction() called more than once. skipping."); - return; - } - - const size_t N = gActiveConnections.size(); - VERBOSE("openGlobalTransaction (%ld clients)", N); - for (size_t i=0; i<N; i++) { - sp<SurfaceComposerClient> client(gActiveConnections.valueAt(i)); - if (gOpenTransactions.indexOf(client) < 0) { - if (client->openTransaction() == NO_ERROR) { - if (gOpenTransactions.add(client) < 0) { - // Ooops! - LOGE( "Unable to add a SurfaceComposerClient " - "to the global transaction set (out of memory?)"); - client->closeTransaction(); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } else { - LOGE("openTransaction on client %p failed", client.get()); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } - } -} - -void SurfaceComposerClient::closeGlobalTransaction() -{ - gLock.lock(); - SortedVector< sp<SurfaceComposerClient> > clients(gOpenTransactions); - gOpenTransactions.clear(); - gLock.unlock(); - - const size_t N = clients.size(); - VERBOSE("closeGlobalTransaction (%ld clients)", N); - if (N == 1) { - clients[0]->closeTransaction(); - } else { - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - sm->openGlobalTransaction(); - for (size_t i=0; i<N; i++) { - clients[i]->closeTransaction(); - } - sm->closeGlobalTransaction(); - } -} - -status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags) -{ - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - return sm->freezeDisplay(dpy, flags); -} - -status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags) -{ - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - return sm->unfreezeDisplay(dpy, flags); -} - -int SurfaceComposerClient::setOrientation(DisplayID dpy, int orientation) -{ - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - return sm->setOrientation(dpy, orientation); -} - -status_t SurfaceComposerClient::openTransaction() -{ - if (mStatus != NO_ERROR) - return mStatus; - Mutex::Autolock _l(mLock); - VERBOSE( "openTransaction (client %p, mTransactionOpen=%d)", - this, mTransactionOpen); - mTransactionOpen++; - if (mPrebuiltLayerState == 0) { - mPrebuiltLayerState = new layer_state_t; - } - return NO_ERROR; -} - - -status_t SurfaceComposerClient::closeTransaction() -{ - if (mStatus != NO_ERROR) - return mStatus; - - Mutex::Autolock _l(mLock); - - VERBOSE( "closeTransaction (client %p, mTransactionOpen=%d)", - this, mTransactionOpen); - - if (mTransactionOpen <= 0) { - LOGE( "closeTransaction (client %p, mTransactionOpen=%d) " - "called more times than openTransaction()", - this, mTransactionOpen); - return INVALID_OPERATION; - } - - if (mTransactionOpen >= 2) { - mTransactionOpen--; - return NO_ERROR; - } - - mTransactionOpen = 0; - const ssize_t count = mStates.size(); - if (count) { - mClient->setState(count, mStates.array()); - mStates.clear(); - } - return NO_ERROR; -} - -layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface) -{ - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface.get()); - if (err != NO_ERROR) - return 0; - - // API usage error, do nothing. - if (mTransactionOpen<=0) { - LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d", - this, int(index), mTransactionOpen); - return 0; - } - - // use mPrebuiltLayerState just to find out if we already have it - layer_state_t& dummy = *mPrebuiltLayerState; - dummy.surface = index; - ssize_t i = mStates.indexOf(dummy); - if (i < 0) { - // we don't have it, add an initialized layer_state to our list - i = mStates.add(dummy); - } - return mStates.editArray() + i; -} - -layer_state_t* SurfaceComposerClient::_lockLayerState(const sp<Surface>& surface) -{ - layer_state_t* s; - mLock.lock(); - s = _get_state_l(surface); - if (!s) mLock.unlock(); - return s; -} - -void SurfaceComposerClient::_unlockLayerState() -{ - mLock.unlock(); -} - -status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t y) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::ePositionChanged; - s->x = x; - s->y = y; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eSizeChanged; - s->w = w; - s->h = h; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eLayerChanged; - s->z = z; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::hide(Surface* surface) -{ - return setFlags(surface, ISurfaceComposer::eLayerHidden, - ISurfaceComposer::eLayerHidden); -} - -status_t SurfaceComposerClient::show(Surface* surface, int32_t) -{ - return setFlags(surface, 0, ISurfaceComposer::eLayerHidden); -} - -status_t SurfaceComposerClient::freeze(Surface* surface) -{ - return setFlags(surface, ISurfaceComposer::eLayerFrozen, - ISurfaceComposer::eLayerFrozen); -} - -status_t SurfaceComposerClient::unfreeze(Surface* surface) -{ - return setFlags(surface, 0, ISurfaceComposer::eLayerFrozen); -} - -status_t SurfaceComposerClient::setFlags(Surface* surface, - uint32_t flags, uint32_t mask) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eVisibilityChanged; - s->flags &= ~mask; - s->flags |= (flags & mask); - s->mask |= mask; - _unlockLayerState(); - return NO_ERROR; -} - - -status_t SurfaceComposerClient::setTransparentRegionHint( - Surface* surface, const Region& transparentRegion) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eTransparentRegionChanged; - s->transparentRegion = transparentRegion; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eAlphaChanged; - s->alpha = alpha; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setMatrix( - Surface* surface, - float dsdx, float dtdx, - float dsdy, float dtdy ) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eMatrixChanged; - layer_state_t::matrix22_t matrix; - matrix.dsdx = dsdx; - matrix.dtdx = dtdx; - matrix.dsdy = dsdy; - matrix.dtdy = dtdy; - s->matrix = matrix; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setFreezeTint(Surface* surface, uint32_t tint) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eFreezeTintChanged; - s->tint = tint; - _unlockLayerState(); - return NO_ERROR; -} - -}; // namespace android - diff --git a/libs/ui/SurfaceFlingerSynchro.cpp b/libs/ui/SurfaceFlingerSynchro.cpp deleted file mode 100644 index 5cd9755..0000000 --- a/libs/ui/SurfaceFlingerSynchro.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlingerSynchro" - -#include <stdint.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <utils/IPCThreadState.h> -#include <utils/Log.h> - -#include <private/ui/SurfaceFlingerSynchro.h> - -namespace android { - -// --------------------------------------------------------------------------- - -SurfaceFlingerSynchro::Barrier::Barrier() - : state(CLOSED) { -} - -SurfaceFlingerSynchro::Barrier::~Barrier() { -} - -void SurfaceFlingerSynchro::Barrier::open() { - asm volatile ("":::"memory"); - Mutex::Autolock _l(lock); - state = OPENED; - cv.broadcast(); -} - -void SurfaceFlingerSynchro::Barrier::close() { - Mutex::Autolock _l(lock); - state = CLOSED; -} - -void SurfaceFlingerSynchro::Barrier::waitAndClose() -{ - Mutex::Autolock _l(lock); - while (state == CLOSED) { - // we're about to wait, flush the binder command buffer - IPCThreadState::self()->flushCommands(); - cv.wait(lock); - } - state = CLOSED; -} - -status_t SurfaceFlingerSynchro::Barrier::waitAndClose(nsecs_t timeout) -{ - Mutex::Autolock _l(lock); - while (state == CLOSED) { - // we're about to wait, flush the binder command buffer - IPCThreadState::self()->flushCommands(); - int err = cv.waitRelative(lock, timeout); - if (err != 0) - return err; - } - state = CLOSED; - return NO_ERROR; -} - -// --------------------------------------------------------------------------- - -SurfaceFlingerSynchro::SurfaceFlingerSynchro(const sp<ISurfaceComposer>& flinger) - : mSurfaceComposer(flinger) -{ -} - -SurfaceFlingerSynchro::SurfaceFlingerSynchro() -{ -} - -SurfaceFlingerSynchro::~SurfaceFlingerSynchro() -{ -} - -status_t SurfaceFlingerSynchro::signal() -{ - mSurfaceComposer->signal(); - return NO_ERROR; -} - -status_t SurfaceFlingerSynchro::wait() -{ - mBarrier.waitAndClose(); - return NO_ERROR; -} - -status_t SurfaceFlingerSynchro::wait(nsecs_t timeout) -{ - if (timeout == 0) - return SurfaceFlingerSynchro::wait(); - return mBarrier.waitAndClose(timeout); -} - -void SurfaceFlingerSynchro::open() -{ - mBarrier.open(); -} - -// --------------------------------------------------------------------------- - -}; // namespace android - diff --git a/libs/ui/Time.cpp b/libs/ui/Time.cpp deleted file mode 100644 index b553913..0000000 --- a/libs/ui/Time.cpp +++ /dev/null @@ -1,199 +0,0 @@ -#include <utils/TimeUtils.h> -#include <stdio.h> -#include <cutils/tztime.h> - -namespace android { - -static void -dump(const Time& t) -{ - #ifdef HAVE_TM_GMTOFF - long tm_gmtoff = t.t.tm_gmtoff; - #else - long tm_gmtoff = 0; - #endif - printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n", - t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday, - t.t.tm_hour, t.t.tm_min, t.t.tm_sec, - t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday); -} - -Time::Time() -{ - t.tm_sec = 0; - t.tm_min = 0; - t.tm_hour = 0; - t.tm_mday = 0; - t.tm_mon = 0; - t.tm_year = 0; - t.tm_wday = 0; - t.tm_yday = 0; - t.tm_isdst = -1; // we don't know, so let the C library determine - #ifdef HAVE_TM_GMTOFF - t.tm_gmtoff = 0; - #endif -} - - -#define COMPARE_FIELD(field) do { \ - int diff = a.t.field - b.t.field; \ - if (diff != 0) return diff; \ - } while(0) - -int -Time::compare(Time& a, Time& b) -{ - if (0 == strcmp(a.timezone, b.timezone)) { - // if the timezones are the same, we can easily compare the two - // times. Otherwise, convert to milliseconds and compare that. - // This requires that object be normalized. - COMPARE_FIELD(tm_year); - COMPARE_FIELD(tm_mon); - COMPARE_FIELD(tm_mday); - COMPARE_FIELD(tm_hour); - COMPARE_FIELD(tm_min); - COMPARE_FIELD(tm_sec); - return 0; - } else { - int64_t am = a.toMillis(false /* use isDst */); - int64_t bm = b.toMillis(false /* use isDst */); - int64_t diff = am-bm; - return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0); - } -} - -static const int DAYS_PER_MONTH[] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - -static inline int days_this_month(int year, int month) -{ - int n = DAYS_PER_MONTH[month]; - if (n != 28) { - return n; - } else { - int y = year; - return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28; - } -} - -void -Time::switchTimezone(const char* timezone) -{ - time_t seconds = mktime_tz(&(this->t), this->timezone); - localtime_tz(&seconds, &(this->t), timezone); -} - -String8 -Time::format(const char *format, const struct strftime_locale *locale) const -{ - char buf[257]; - int n = strftime_tz(buf, 257, format, &(this->t), locale); - if (n > 0) { - return String8(buf); - } else { - return String8(); - } -} - -static inline short -tochar(int n) -{ - return (n >= 0 && n <= 9) ? ('0'+n) : ' '; -} - -static inline short -next_char(int *m, int k) -{ - int n = *m / k; - *m = *m % k; - return tochar(n); -} - -void -Time::format2445(short* buf, bool hasTime) const -{ - int n; - - n = t.tm_year+1900; - buf[0] = next_char(&n, 1000); - buf[1] = next_char(&n, 100); - buf[2] = next_char(&n, 10); - buf[3] = tochar(n); - - n = t.tm_mon+1; - buf[4] = next_char(&n, 10); - buf[5] = tochar(n); - - n = t.tm_mday; - buf[6] = next_char(&n, 10); - buf[7] = tochar(n); - - if (hasTime) { - buf[8] = 'T'; - - n = t.tm_hour; - buf[9] = next_char(&n, 10); - buf[10] = tochar(n); - - n = t.tm_min; - buf[11] = next_char(&n, 10); - buf[12] = tochar(n); - - n = t.tm_sec; - buf[13] = next_char(&n, 10); - buf[14] = tochar(n); - bool inUtc = strcmp("UTC", timezone) == 0; - if (inUtc) { - buf[15] = 'Z'; - } - } -} - -String8 -Time::toString() const -{ - String8 str; - char* s = str.lockBuffer(150); - #ifdef HAVE_TM_GMTOFF - long tm_gmtoff = t.tm_gmtoff; - #else - long tm_gmtoff = 0; - #endif - sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)", - t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, - t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst, - (int)(((Time*)this)->toMillis(false /* use isDst */)/1000)); - str.unlockBuffer(); - return str; -} - -void -Time::setToNow() -{ - time_t seconds; - time(&seconds); - localtime_tz(&seconds, &(this->t), this->timezone); -} - -int64_t -Time::toMillis(bool ignoreDst) -{ - if (ignoreDst) { - this->t.tm_isdst = -1; - } - int64_t r = mktime_tz(&(this->t), this->timezone); - if (r == -1) - return -1; - return r * 1000; -} - -void -Time::set(int64_t millis) -{ - time_t seconds = millis / 1000; - localtime_tz(&seconds, &(this->t), this->timezone); -} - -}; // namespace android - diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk deleted file mode 100644 index cdb8ca2..0000000 --- a/libs/utils/Android.mk +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH:= $(call my-dir) - -# libutils is a little unique: It's built twice, once for the host -# and once for the device. - -commonSources:= \ - Asset.cpp \ - AssetDir.cpp \ - AssetManager.cpp \ - BufferedTextOutput.cpp \ - CallStack.cpp \ - Debug.cpp \ - FileMap.cpp \ - RefBase.cpp \ - ResourceTypes.cpp \ - SharedBuffer.cpp \ - Static.cpp \ - StopWatch.cpp \ - String8.cpp \ - String16.cpp \ - SystemClock.cpp \ - TextOutput.cpp \ - Threads.cpp \ - TimerProbe.cpp \ - Timers.cpp \ - VectorImpl.cpp \ - ZipFileCRO.cpp \ - ZipFileRO.cpp \ - ZipUtils.cpp \ - misc.cpp \ - ported.cpp \ - LogSocket.cpp - -# -# The cpp files listed here do not belong in the device -# build. Consult with the swetland before even thinking about -# putting them in commonSources. -# -# They're used by the simulator runtime and by host-side tools like -# aapt and the simulator front-end. -# -hostSources:= \ - InetAddress.cpp \ - Pipe.cpp \ - Socket.cpp \ - ZipEntry.cpp \ - ZipFile.cpp - -# For the host -# ===================================================== - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= $(commonSources) $(hostSources) - -ifeq ($(HOST_OS),linux) -# Use the futex based mutex and condition variable -# implementation from android-arm because it's shared mem safe - LOCAL_SRC_FILES += \ - futex_synchro.c \ - executablepath_linux.cpp -endif -ifeq ($(HOST_OS),darwin) - LOCAL_SRC_FILES += \ - executablepath_darwin.cpp -endif - -LOCAL_MODULE:= libutils - -LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -LOCAL_C_INCLUDES += external/zlib - -ifeq ($(HOST_OS),windows) -ifeq ($(strip $(USE_CYGWIN),),) -# Under MinGW, ctype.h doesn't need multi-byte support -LOCAL_CFLAGS += -DMB_CUR_MAX=1 -endif -endif - -include $(BUILD_HOST_STATIC_LIBRARY) - - - -# For the device -# ===================================================== -include $(CLEAR_VARS) - - -# we have the common sources, plus some device-specific stuff -LOCAL_SRC_FILES:= \ - $(commonSources) \ - Binder.cpp \ - BpBinder.cpp \ - IInterface.cpp \ - IMemory.cpp \ - IPCThreadState.cpp \ - MemoryDealer.cpp \ - MemoryBase.cpp \ - MemoryHeapBase.cpp \ - MemoryHeapPmem.cpp \ - Parcel.cpp \ - ProcessState.cpp \ - IPermissionController.cpp \ - IServiceManager.cpp \ - Unicode.cpp - -ifeq ($(TARGET_SIMULATOR),true) -LOCAL_SRC_FILES += $(hostSources) -endif - -ifeq ($(TARGET_OS),linux) -# Use the futex based mutex and condition variable -# implementation from android-arm because it's shared mem safe -LOCAL_SRC_FILES += futex_synchro.c -LOCAL_LDLIBS += -lrt -ldl -endif - -LOCAL_C_INCLUDES += \ - external/zlib \ - external/icu4c/common -LOCAL_LDLIBS += -lpthread - -LOCAL_SHARED_LIBRARIES := \ - libz \ - liblog \ - libcutils - -ifneq ($(TARGET_SIMULATOR),true) -ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86) -# This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp -LOCAL_SHARED_LIBRARIES += \ - libdl -endif # linux-x86 -endif # sim - -LOCAL_MODULE:= libutils - -#LOCAL_CFLAGS+= -#LOCAL_LDFLAGS:= - -include $(BUILD_SHARED_LIBRARY) - diff --git a/libs/utils/Asset.cpp b/libs/utils/Asset.cpp deleted file mode 100644 index 91203dd..0000000 --- a/libs/utils/Asset.cpp +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Provide access to a read-only asset. -// - -#define LOG_TAG "asset" -//#define NDEBUG 0 - -#include <utils/Asset.h> -#include <utils/Atomic.h> -#include <utils/FileMap.h> -#include <utils/ZipUtils.h> -#include <utils/ZipFileRO.h> -#include <utils/Log.h> - -#include <string.h> -#include <memory.h> -#include <fcntl.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - -#ifndef O_BINARY -# define O_BINARY 0 -#endif - -static volatile int32_t gCount = 0; - -int32_t Asset::getGlobalCount() -{ - return gCount; -} - -Asset::Asset(void) - : mAccessMode(ACCESS_UNKNOWN) -{ - int count = android_atomic_inc(&gCount)+1; - //LOGI("Creating Asset %p #%d\n", this, count); -} - -Asset::~Asset(void) -{ - int count = android_atomic_dec(&gCount); - //LOGI("Destroying Asset in %p #%d\n", this, count); -} - -/* - * Create a new Asset from a file on disk. There is a fair chance that - * the file doesn't actually exist. - * - * We can use "mode" to decide how we want to go about it. - */ -/*static*/ Asset* Asset::createFromFile(const char* fileName, AccessMode mode) -{ - _FileAsset* pAsset; - status_t result; - off_t length; - int fd; - - fd = open(fileName, O_RDONLY | O_BINARY); - if (fd < 0) - return NULL; - - /* - * Under Linux, the lseek fails if we actually opened a directory. To - * be correct we should test the file type explicitly, but since we - * always open things read-only it doesn't really matter, so there's - * no value in incurring the extra overhead of an fstat() call. - */ - length = lseek(fd, 0, SEEK_END); - if (length < 0) { - ::close(fd); - return NULL; - } - (void) lseek(fd, 0, SEEK_SET); - - pAsset = new _FileAsset; - result = pAsset->openChunk(fileName, fd, 0, length); - if (result != NO_ERROR) { - delete pAsset; - return NULL; - } - - pAsset->mAccessMode = mode; - return pAsset; -} - - -/* - * Create a new Asset from a compressed file on disk. There is a fair chance - * that the file doesn't actually exist. - * - * We currently support gzip files. We might want to handle .bz2 someday. - */ -/*static*/ Asset* Asset::createFromCompressedFile(const char* fileName, - AccessMode mode) -{ - _CompressedAsset* pAsset; - status_t result; - off_t fileLen; - bool scanResult; - long offset; - int method; - long uncompressedLen, compressedLen; - int fd; - - fd = open(fileName, O_RDONLY | O_BINARY); - if (fd < 0) - return NULL; - - fileLen = lseek(fd, 0, SEEK_END); - if (fileLen < 0) { - ::close(fd); - return NULL; - } - (void) lseek(fd, 0, SEEK_SET); - - /* want buffered I/O for the file scan; must dup so fclose() is safe */ - FILE* fp = fdopen(dup(fd), "rb"); - if (fp == NULL) { - ::close(fd); - return NULL; - } - - unsigned long crc32; - scanResult = ZipUtils::examineGzip(fp, &method, &uncompressedLen, - &compressedLen, &crc32); - offset = ftell(fp); - fclose(fp); - if (!scanResult) { - LOGD("File '%s' is not in gzip format\n", fileName); - ::close(fd); - return NULL; - } - - pAsset = new _CompressedAsset; - result = pAsset->openChunk(fd, offset, method, uncompressedLen, - compressedLen); - if (result != NO_ERROR) { - delete pAsset; - return NULL; - } - - pAsset->mAccessMode = mode; - return pAsset; -} - - -#if 0 -/* - * Create a new Asset from part of an open file. - */ -/*static*/ Asset* Asset::createFromFileSegment(int fd, off_t offset, - size_t length, AccessMode mode) -{ - _FileAsset* pAsset; - status_t result; - - pAsset = new _FileAsset; - result = pAsset->openChunk(NULL, fd, offset, length); - if (result != NO_ERROR) - return NULL; - - pAsset->mAccessMode = mode; - return pAsset; -} - -/* - * Create a new Asset from compressed data in an open file. - */ -/*static*/ Asset* Asset::createFromCompressedData(int fd, off_t offset, - int compressionMethod, size_t uncompressedLen, size_t compressedLen, - AccessMode mode) -{ - _CompressedAsset* pAsset; - status_t result; - - pAsset = new _CompressedAsset; - result = pAsset->openChunk(fd, offset, compressionMethod, - uncompressedLen, compressedLen); - if (result != NO_ERROR) - return NULL; - - pAsset->mAccessMode = mode; - return pAsset; -} -#endif - -/* - * Create a new Asset from a memory mapping. - */ -/*static*/ Asset* Asset::createFromUncompressedMap(FileMap* dataMap, - AccessMode mode) -{ - _FileAsset* pAsset; - status_t result; - - pAsset = new _FileAsset; - result = pAsset->openChunk(dataMap); - if (result != NO_ERROR) - return NULL; - - pAsset->mAccessMode = mode; - return pAsset; -} - -/* - * Create a new Asset from compressed data in a memory mapping. - */ -/*static*/ Asset* Asset::createFromCompressedMap(FileMap* dataMap, - int method, size_t uncompressedLen, AccessMode mode) -{ - _CompressedAsset* pAsset; - status_t result; - - pAsset = new _CompressedAsset; - result = pAsset->openChunk(dataMap, method, uncompressedLen); - if (result != NO_ERROR) - return NULL; - - pAsset->mAccessMode = mode; - return pAsset; -} - - -/* - * Do generic seek() housekeeping. Pass in the offset/whence values from - * the seek request, along with the current chunk offset and the chunk - * length. - * - * Returns the new chunk offset, or -1 if the seek is illegal. - */ -off_t Asset::handleSeek(off_t offset, int whence, off_t curPosn, off_t maxPosn) -{ - off_t newOffset; - - switch (whence) { - case SEEK_SET: - newOffset = offset; - break; - case SEEK_CUR: - newOffset = curPosn + offset; - break; - case SEEK_END: - newOffset = maxPosn + offset; - break; - default: - LOGW("unexpected whence %d\n", whence); - // this was happening due to an off_t size mismatch - assert(false); - return (off_t) -1; - } - - if (newOffset < 0 || newOffset > maxPosn) { - LOGW("seek out of range: want %ld, end=%ld\n", - (long) newOffset, (long) maxPosn); - return (off_t) -1; - } - - return newOffset; -} - - -/* - * =========================================================================== - * _FileAsset - * =========================================================================== - */ - -/* - * Constructor. - */ -_FileAsset::_FileAsset(void) - : mStart(0), mLength(0), mOffset(0), mFp(NULL), mFileName(NULL), mMap(NULL), mBuf(NULL) -{ -} - -/* - * Destructor. Release resources. - */ -_FileAsset::~_FileAsset(void) -{ - close(); -} - -/* - * Operate on a chunk of an uncompressed file. - * - * Zero-length chunks are allowed. - */ -status_t _FileAsset::openChunk(const char* fileName, int fd, off_t offset, size_t length) -{ - assert(mFp == NULL); // no reopen - assert(mMap == NULL); - assert(fd >= 0); - assert(offset >= 0); - - /* - * Seek to end to get file length. - */ - off_t fileLength; - fileLength = lseek(fd, 0, SEEK_END); - if (fileLength == (off_t) -1) { - // probably a bad file descriptor - LOGD("failed lseek (errno=%d)\n", errno); - return UNKNOWN_ERROR; - } - - if ((off_t) (offset + length) > fileLength) { - LOGD("start (%ld) + len (%ld) > end (%ld)\n", - (long) offset, (long) length, (long) fileLength); - return BAD_INDEX; - } - - /* after fdopen, the fd will be closed on fclose() */ - mFp = fdopen(fd, "rb"); - if (mFp == NULL) - return UNKNOWN_ERROR; - - mStart = offset; - mLength = length; - assert(mOffset == 0); - - /* seek the FILE* to the start of chunk */ - if (fseek(mFp, mStart, SEEK_SET) != 0) { - assert(false); - } - - mFileName = fileName != NULL ? strdup(fileName) : NULL; - - return NO_ERROR; -} - -/* - * Create the chunk from the map. - */ -status_t _FileAsset::openChunk(FileMap* dataMap) -{ - assert(mFp == NULL); // no reopen - assert(mMap == NULL); - assert(dataMap != NULL); - - mMap = dataMap; - mStart = -1; // not used - mLength = dataMap->getDataLength(); - assert(mOffset == 0); - - return NO_ERROR; -} - -/* - * Read a chunk of data. - */ -ssize_t _FileAsset::read(void* buf, size_t count) -{ - size_t maxLen; - size_t actual; - - assert(mOffset >= 0 && mOffset <= mLength); - - if (getAccessMode() == ACCESS_BUFFER) { - /* - * On first access, read or map the entire file. The caller has - * requested buffer access, either because they're going to be - * using the buffer or because what they're doing has appropriate - * performance needs and access patterns. - */ - if (mBuf == NULL) - getBuffer(false); - } - - /* adjust count if we're near EOF */ - maxLen = mLength - mOffset; - if (count > maxLen) - count = maxLen; - - if (!count) - return 0; - - if (mMap != NULL) { - /* copy from mapped area */ - //printf("map read\n"); - memcpy(buf, (char*)mMap->getDataPtr() + mOffset, count); - actual = count; - } else if (mBuf != NULL) { - /* copy from buffer */ - //printf("buf read\n"); - memcpy(buf, (char*)mBuf + mOffset, count); - actual = count; - } else { - /* read from the file */ - //printf("file read\n"); - if (ftell(mFp) != mStart + mOffset) { - LOGE("Hosed: %ld != %ld+%ld\n", - ftell(mFp), (long) mStart, (long) mOffset); - assert(false); - } - - /* - * This returns 0 on error or eof. We need to use ferror() or feof() - * to tell the difference, but we don't currently have those on the - * device. However, we know how much data is *supposed* to be in the - * file, so if we don't read the full amount we know something is - * hosed. - */ - actual = fread(buf, 1, count, mFp); - if (actual == 0) // something failed -- I/O error? - return -1; - - assert(actual == count); - } - - mOffset += actual; - return actual; -} - -/* - * Seek to a new position. - */ -off_t _FileAsset::seek(off_t offset, int whence) -{ - off_t newPosn; - long actualOffset; - - // compute new position within chunk - newPosn = handleSeek(offset, whence, mOffset, mLength); - if (newPosn == (off_t) -1) - return newPosn; - - actualOffset = (long) (mStart + newPosn); - - if (mFp != NULL) { - if (fseek(mFp, (long) actualOffset, SEEK_SET) != 0) - return (off_t) -1; - } - - mOffset = actualOffset - mStart; - return mOffset; -} - -/* - * Close the asset. - */ -void _FileAsset::close(void) -{ - if (mMap != NULL) { - mMap->release(); - mMap = NULL; - } - if (mBuf != NULL) { - delete[] mBuf; - mBuf = NULL; - } - - if (mFileName != NULL) { - free(mFileName); - mFileName = NULL; - } - - if (mFp != NULL) { - // can only be NULL when called from destructor - // (otherwise we would never return this object) - fclose(mFp); - mFp = NULL; - } -} - -/* - * Return a read-only pointer to a buffer. - * - * We can either read the whole thing in or map the relevant piece of - * the source file. Ideally a map would be established at a higher - * level and we'd be using a different object, but we didn't, so we - * deal with it here. - */ -const void* _FileAsset::getBuffer(bool wordAligned) -{ - /* subsequent requests just use what we did previously */ - if (mBuf != NULL) - return mBuf; - if (mMap != NULL) { - if (!wordAligned) { - return mMap->getDataPtr(); - } - return ensureAlignment(mMap); - } - - assert(mFp != NULL); - - if (mLength < kReadVsMapThreshold) { - unsigned char* buf; - long allocLen; - - /* zero-length files are allowed; not sure about zero-len allocs */ - /* (works fine with gcc + x86linux) */ - allocLen = mLength; - if (mLength == 0) - allocLen = 1; - - buf = new unsigned char[allocLen]; - if (buf == NULL) { - LOGE("alloc of %ld bytes failed\n", (long) allocLen); - return NULL; - } - - LOGV("Asset %p allocating buffer size %d (smaller than threshold)", this, (int)allocLen); - if (mLength > 0) { - long oldPosn = ftell(mFp); - fseek(mFp, mStart, SEEK_SET); - if (fread(buf, 1, mLength, mFp) != (size_t) mLength) { - LOGE("failed reading %ld bytes\n", (long) mLength); - delete[] buf; - return NULL; - } - fseek(mFp, oldPosn, SEEK_SET); - } - - LOGV(" getBuffer: loaded into buffer\n"); - - mBuf = buf; - return mBuf; - } else { - FileMap* map; - - map = new FileMap; - if (!map->create(NULL, fileno(mFp), mStart, mLength, true)) { - map->release(); - return NULL; - } - - LOGV(" getBuffer: mapped\n"); - - mMap = map; - if (!wordAligned) { - return mMap->getDataPtr(); - } - return ensureAlignment(mMap); - } -} - -int _FileAsset::openFileDescriptor(off_t* outStart, off_t* outLength) const -{ - if (mMap != NULL) { - const char* fname = mMap->getFileName(); - if (fname == NULL) { - fname = mFileName; - } - if (fname == NULL) { - return -1; - } - *outStart = mMap->getDataOffset(); - *outLength = mMap->getDataLength(); - return open(fname, O_RDONLY | O_BINARY); - } - if (mFileName == NULL) { - return -1; - } - *outStart = mStart; - *outLength = mLength; - return open(mFileName, O_RDONLY | O_BINARY); -} - -const void* _FileAsset::ensureAlignment(FileMap* map) -{ - void* data = map->getDataPtr(); - if ((((size_t)data)&0x3) == 0) { - // We can return this directly if it is aligned on a word - // boundary. - return data; - } - // If not aligned on a word boundary, then we need to copy it into - // our own buffer. - LOGV("Copying FileAsset %p to buffer size %d to make it aligned.", this, (int)mLength); - unsigned char* buf = new unsigned char[mLength]; - if (buf == NULL) { - LOGE("alloc of %ld bytes failed\n", (long) mLength); - return NULL; - } - memcpy(buf, data, mLength); - mBuf = buf; - return buf; -} - -/* - * =========================================================================== - * _CompressedAsset - * =========================================================================== - */ - -/* - * Constructor. - */ -_CompressedAsset::_CompressedAsset(void) - : mStart(0), mCompressedLen(0), mUncompressedLen(0), mOffset(0), - mMap(NULL), mFd(-1), mBuf(NULL) -{ -} - -/* - * Destructor. Release resources. - */ -_CompressedAsset::~_CompressedAsset(void) -{ - close(); -} - -/* - * Open a chunk of compressed data inside a file. - * - * This currently just sets up some values and returns. On the first - * read, we expand the entire file into a buffer and return data from it. - */ -status_t _CompressedAsset::openChunk(int fd, off_t offset, - int compressionMethod, size_t uncompressedLen, size_t compressedLen) -{ - assert(mFd < 0); // no re-open - assert(mMap == NULL); - assert(fd >= 0); - assert(offset >= 0); - assert(compressedLen > 0); - - if (compressionMethod != ZipFileRO::kCompressDeflated) { - assert(false); - return UNKNOWN_ERROR; - } - - mStart = offset; - mCompressedLen = compressedLen; - mUncompressedLen = uncompressedLen; - assert(mOffset == 0); - mFd = fd; - assert(mBuf == NULL); - - return NO_ERROR; -} - -/* - * Open a chunk of compressed data in a mapped region. - * - * Nothing is expanded until the first read call. - */ -status_t _CompressedAsset::openChunk(FileMap* dataMap, int compressionMethod, - size_t uncompressedLen) -{ - assert(mFd < 0); // no re-open - assert(mMap == NULL); - assert(dataMap != NULL); - - if (compressionMethod != ZipFileRO::kCompressDeflated) { - assert(false); - return UNKNOWN_ERROR; - } - - mMap = dataMap; - mStart = -1; // not used - mCompressedLen = dataMap->getDataLength(); - mUncompressedLen = uncompressedLen; - assert(mOffset == 0); - - return NO_ERROR; -} - -/* - * Read data from a chunk of compressed data. - * - * [For now, that's just copying data out of a buffer.] - */ -ssize_t _CompressedAsset::read(void* buf, size_t count) -{ - size_t maxLen; - size_t actual; - - assert(mOffset >= 0 && mOffset <= mUncompressedLen); - - // TODO: if mAccessMode == ACCESS_STREAMING, use zlib more cleverly - - if (mBuf == NULL) { - if (getBuffer(false) == NULL) - return -1; - } - assert(mBuf != NULL); - - /* adjust count if we're near EOF */ - maxLen = mUncompressedLen - mOffset; - if (count > maxLen) - count = maxLen; - - if (!count) - return 0; - - /* copy from buffer */ - //printf("comp buf read\n"); - memcpy(buf, (char*)mBuf + mOffset, count); - actual = count; - - mOffset += actual; - return actual; -} - -/* - * Handle a seek request. - * - * If we're working in a streaming mode, this is going to be fairly - * expensive, because it requires plowing through a bunch of compressed - * data. - */ -off_t _CompressedAsset::seek(off_t offset, int whence) -{ - off_t newPosn; - - // compute new position within chunk - newPosn = handleSeek(offset, whence, mOffset, mUncompressedLen); - if (newPosn == (off_t) -1) - return newPosn; - - mOffset = newPosn; - return mOffset; -} - -/* - * Close the asset. - */ -void _CompressedAsset::close(void) -{ - if (mMap != NULL) { - mMap->release(); - mMap = NULL; - } - if (mBuf != NULL) { - delete[] mBuf; - mBuf = NULL; - } - - if (mFd > 0) { - ::close(mFd); - mFd = -1; - } -} - -/* - * Get a pointer to a read-only buffer of data. - * - * The first time this is called, we expand the compressed data into a - * buffer. - */ -const void* _CompressedAsset::getBuffer(bool wordAligned) -{ - unsigned char* buf = NULL; - - if (mBuf != NULL) - return mBuf; - - if (mUncompressedLen > UNCOMPRESS_DATA_MAX) { - LOGD("Data exceeds UNCOMPRESS_DATA_MAX (%ld vs %d)\n", - (long) mUncompressedLen, UNCOMPRESS_DATA_MAX); - goto bail; - } - - /* - * Allocate a buffer and read the file into it. - */ - buf = new unsigned char[mUncompressedLen]; - if (buf == NULL) { - LOGW("alloc %ld bytes failed\n", (long) mUncompressedLen); - goto bail; - } - - if (mMap != NULL) { - if (!ZipFileRO::inflateBuffer(buf, mMap->getDataPtr(), - mUncompressedLen, mCompressedLen)) - goto bail; - } else { - assert(mFd >= 0); - - /* - * Seek to the start of the compressed data. - */ - if (lseek(mFd, mStart, SEEK_SET) != mStart) - goto bail; - - /* - * Expand the data into it. - */ - if (!ZipUtils::inflateToBuffer(mFd, buf, mUncompressedLen, - mCompressedLen)) - goto bail; - } - - /* success! */ - mBuf = buf; - buf = NULL; - -bail: - delete[] buf; - return mBuf; -} - diff --git a/libs/utils/AssetDir.cpp b/libs/utils/AssetDir.cpp deleted file mode 100644 index c5f664e..0000000 --- a/libs/utils/AssetDir.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Provide access to a virtual directory in "asset space". Most of the -// implementation is in the header file or in friend functions in -// AssetManager. -// -#include <utils/AssetDir.h> - -using namespace android; - - -/* - * Find a matching entry in a vector of FileInfo. Because it's sorted, we - * can use a binary search. - * - * Assumes the vector is sorted in ascending order. - */ -/*static*/ int AssetDir::FileInfo::findEntry(const SortedVector<FileInfo>* pVector, - const String8& fileName) -{ - FileInfo tmpInfo; - - tmpInfo.setFileName(fileName); - return pVector->indexOf(tmpInfo); - -#if 0 // don't need this after all (uses 1/2 compares of SortedVector though) - int lo, hi, cur; - - lo = 0; - hi = pVector->size() -1; - while (lo <= hi) { - int cmp; - - cur = (hi + lo) / 2; - cmp = strcmp(pVector->itemAt(cur).getFileName(), fileName); - if (cmp == 0) { - /* match, bail */ - return cur; - } else if (cmp < 0) { - /* too low */ - lo = cur + 1; - } else { - /* too high */ - hi = cur -1; - } - } - - return -1; -#endif -} - diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp deleted file mode 100644 index 447b801..0000000 --- a/libs/utils/AssetManager.cpp +++ /dev/null @@ -1,1637 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Provide access to read-only assets. -// - -#define LOG_TAG "asset" -//#define LOG_NDEBUG 0 - -#include <utils/AssetManager.h> -#include <utils/AssetDir.h> -#include <utils/Asset.h> -#include <utils/Atomic.h> -#include <utils/String8.h> -#include <utils/ResourceTypes.h> -#include <utils/String8.h> -#include <utils/ZipFileRO.h> -#include <utils/Log.h> -#include <utils/Timers.h> -#include <utils/threads.h> - -#include <dirent.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - -/* - * Names for default app, locale, and vendor. We might want to change - * these to be an actual locale, e.g. always use en-US as the default. - */ -static const char* kDefaultLocale = "default"; -static const char* kDefaultVendor = "default"; -static const char* kAssetsRoot = "assets"; -static const char* kAppZipName = NULL; //"classes.jar"; -static const char* kSystemAssets = "framework/framework-res.apk"; - -static const char* kExcludeExtension = ".EXCLUDE"; - -static Asset* const kExcludedAsset = (Asset*) 0xd000000d; - -static volatile int32_t gCount = 0; - - -/* - * =========================================================================== - * AssetManager - * =========================================================================== - */ - -int32_t AssetManager::getGlobalCount() -{ - return gCount; -} - -AssetManager::AssetManager(CacheMode cacheMode) - : mLocale(NULL), mVendor(NULL), - mResources(NULL), mConfig(new ResTable_config), - mCacheMode(cacheMode), mCacheValid(false) -{ - int count = android_atomic_inc(&gCount)+1; - //LOGI("Creating AssetManager %p #%d\n", this, count); - memset(mConfig, 0, sizeof(ResTable_config)); -} - -AssetManager::~AssetManager(void) -{ - int count = android_atomic_dec(&gCount); - //LOGI("Destroying AssetManager in %p #%d\n", this, count); - - delete mConfig; - delete mResources; - - // don't have a String class yet, so make sure we clean up - delete[] mLocale; - delete[] mVendor; -} - -bool AssetManager::addAssetPath(const String8& path, void** cookie) -{ - AutoMutex _l(mLock); - - asset_path ap; - - String8 realPath(path); - if (kAppZipName) { - realPath.appendPath(kAppZipName); - } - ap.type = ::getFileType(realPath.string()); - if (ap.type == kFileTypeRegular) { - ap.path = realPath; - } else { - ap.path = path; - ap.type = ::getFileType(path.string()); - if (ap.type != kFileTypeDirectory && ap.type != kFileTypeRegular) { - LOGW("Asset path %s is neither a directory nor file (type=%d).", - path.string(), (int)ap.type); - return false; - } - } - - // Skip if we have it already. - for (size_t i=0; i<mAssetPaths.size(); i++) { - if (mAssetPaths[i].path == ap.path) { - if (cookie) { - *cookie = (void*)(i+1); - } - return true; - } - } - - LOGV("In %p Asset %s path: %s", this, - ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string()); - - mAssetPaths.add(ap); - - // new paths are always added at the end - if (cookie) { - *cookie = (void*)mAssetPaths.size(); - } - - return true; -} - -bool AssetManager::addDefaultAssets() -{ - const char* root = getenv("ANDROID_ROOT"); - LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set"); - - String8 path(root); - path.appendPath(kSystemAssets); - - return addAssetPath(path, NULL); -} - -void* AssetManager::nextAssetPath(void* cookie) const -{ - AutoMutex _l(mLock); - size_t next = ((size_t)cookie)+1; - return next > mAssetPaths.size() ? NULL : (void*)next; -} - -String8 AssetManager::getAssetPath(void* cookie) const -{ - AutoMutex _l(mLock); - const size_t which = ((size_t)cookie)-1; - if (which < mAssetPaths.size()) { - return mAssetPaths[which].path; - } - return String8(); -} - -/* - * Set the current locale. Use NULL to indicate no locale. - * - * Close and reopen Zip archives as appropriate, and reset cached - * information in the locale-specific sections of the tree. - */ -void AssetManager::setLocale(const char* locale) -{ - AutoMutex _l(mLock); - setLocaleLocked(locale); -} - -void AssetManager::setLocaleLocked(const char* locale) -{ - if (mLocale != NULL) { - /* previously set, purge cached data */ - purgeFileNameCacheLocked(); - //mZipSet.purgeLocale(); - delete[] mLocale; - } - mLocale = strdupNew(locale); - - updateResourceParamsLocked(); -} - -/* - * Set the current vendor. Use NULL to indicate no vendor. - * - * Close and reopen Zip archives as appropriate, and reset cached - * information in the vendor-specific sections of the tree. - */ -void AssetManager::setVendor(const char* vendor) -{ - AutoMutex _l(mLock); - - if (mVendor != NULL) { - /* previously set, purge cached data */ - purgeFileNameCacheLocked(); - //mZipSet.purgeVendor(); - delete[] mVendor; - } - mVendor = strdupNew(vendor); -} - -void AssetManager::setConfiguration(const ResTable_config& config, const char* locale) -{ - AutoMutex _l(mLock); - *mConfig = config; - if (locale) { - setLocaleLocked(locale); - } else if (config.language[0] != 0) { - char spec[9]; - spec[0] = config.language[0]; - spec[1] = config.language[1]; - if (config.country[0] != 0) { - spec[2] = '_'; - spec[3] = config.country[0]; - spec[4] = config.country[1]; - spec[5] = 0; - } else { - spec[3] = 0; - } - setLocaleLocked(spec); - } else { - updateResourceParamsLocked(); - } -} - -/* - * Open an asset. - * - * The data could be; - * - In a file on disk (assetBase + fileName). - * - In a compressed file on disk (assetBase + fileName.gz). - * - In a Zip archive, uncompressed or compressed. - * - * It can be in a number of different directories and Zip archives. - * The search order is: - * - [appname] - * - locale + vendor - * - "default" + vendor - * - locale + "default" - * - "default + "default" - * - "common" - * - (same as above) - * - * To find a particular file, we have to try up to eight paths with - * all three forms of data. - * - * We should probably reject requests for "illegal" filenames, e.g. those - * with illegal characters or "../" backward relative paths. - */ -Asset* AssetManager::open(const char* fileName, AccessMode mode) -{ - AutoMutex _l(mLock); - - LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); - - - if (mCacheMode != CACHE_OFF && !mCacheValid) - loadFileNameCacheLocked(); - - String8 assetName(kAssetsRoot); - assetName.appendPath(fileName); - - /* - * For each top-level asset path, search for the asset. - */ - - size_t i = mAssetPaths.size(); - while (i > 0) { - i--; - LOGV("Looking for asset '%s' in '%s'\n", - assetName.string(), mAssetPaths.itemAt(i).path.string()); - Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, mAssetPaths.itemAt(i)); - if (pAsset != NULL) { - return pAsset != kExcludedAsset ? pAsset : NULL; - } - } - - return NULL; -} - -/* - * Open a non-asset file as if it were an asset. - * - * The "fileName" is the partial path starting from the application - * name. - */ -Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode) -{ - AutoMutex _l(mLock); - - LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); - - - if (mCacheMode != CACHE_OFF && !mCacheValid) - loadFileNameCacheLocked(); - - /* - * For each top-level asset path, search for the asset. - */ - - size_t i = mAssetPaths.size(); - while (i > 0) { - i--; - LOGV("Looking for non-asset '%s' in '%s'\n", fileName, mAssetPaths.itemAt(i).path.string()); - Asset* pAsset = openNonAssetInPathLocked( - fileName, mode, mAssetPaths.itemAt(i)); - if (pAsset != NULL) { - return pAsset != kExcludedAsset ? pAsset : NULL; - } - } - - return NULL; -} - -Asset* AssetManager::openNonAsset(void* cookie, const char* fileName, AccessMode mode) -{ - const size_t which = ((size_t)cookie)-1; - - AutoMutex _l(mLock); - - LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); - - - if (mCacheMode != CACHE_OFF && !mCacheValid) - loadFileNameCacheLocked(); - - if (which < mAssetPaths.size()) { - LOGV("Looking for non-asset '%s' in '%s'\n", fileName, - mAssetPaths.itemAt(which).path.string()); - Asset* pAsset = openNonAssetInPathLocked( - fileName, mode, mAssetPaths.itemAt(which)); - if (pAsset != NULL) { - return pAsset != kExcludedAsset ? pAsset : NULL; - } - } - - return NULL; -} - -/* - * Get the type of a file in the asset namespace. - * - * This currently only works for regular files. All others (including - * directories) will return kFileTypeNonexistent. - */ -FileType AssetManager::getFileType(const char* fileName) -{ - Asset* pAsset = NULL; - - /* - * Open the asset. This is less efficient than simply finding the - * file, but it's not too bad (we don't uncompress or mmap data until - * the first read() call). - */ - pAsset = open(fileName, Asset::ACCESS_STREAMING); - delete pAsset; - - if (pAsset == NULL) - return kFileTypeNonexistent; - else - return kFileTypeRegular; -} - -const ResTable* AssetManager::getResTable(bool required) const -{ - ResTable* rt = mResources; - if (rt) { - return rt; - } - - // Iterate through all asset packages, collecting resources from each. - - AutoMutex _l(mLock); - - if (mResources != NULL) { - return mResources; - } - - if (required) { - LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); - } - - if (mCacheMode != CACHE_OFF && !mCacheValid) - const_cast<AssetManager*>(this)->loadFileNameCacheLocked(); - - const size_t N = mAssetPaths.size(); - for (size_t i=0; i<N; i++) { - Asset* ass = NULL; - bool shared = true; - const asset_path& ap = mAssetPaths.itemAt(i); - LOGV("Looking for resource asset in '%s'\n", ap.path.string()); - if (ap.type != kFileTypeDirectory) { - ass = const_cast<AssetManager*>(this)-> - mZipSet.getZipResourceTable(ap.path); - if (ass == NULL) { - LOGV("loading resource table %s\n", ap.path.string()); - ass = const_cast<AssetManager*>(this)-> - openNonAssetInPathLocked("resources.arsc", - Asset::ACCESS_BUFFER, - ap); - if (ass != NULL && ass != kExcludedAsset) { - ass = const_cast<AssetManager*>(this)-> - mZipSet.setZipResourceTable(ap.path, ass); - } - } - } else { - LOGV("loading resource table %s\n", ap.path.string()); - Asset* ass = const_cast<AssetManager*>(this)-> - openNonAssetInPathLocked("resources.arsc", - Asset::ACCESS_BUFFER, - ap); - shared = false; - } - if (ass != NULL && ass != kExcludedAsset) { - if (rt == NULL) { - mResources = rt = new ResTable(); - updateResourceParamsLocked(); - } - LOGV("Installing resource asset %p in to table %p\n", ass, mResources); - rt->add(ass, (void*)(i+1), !shared); - - if (!shared) { - delete ass; - } - } - } - - if (required && !rt) LOGW("Unable to find resources file resources.arsc"); - if (!rt) { - mResources = rt = new ResTable(); - } - return rt; -} - -void AssetManager::updateResourceParamsLocked() const -{ - ResTable* res = mResources; - if (!res) { - return; - } - - size_t llen = mLocale ? strlen(mLocale) : 0; - mConfig->language[0] = 0; - mConfig->language[1] = 0; - mConfig->country[0] = 0; - mConfig->country[1] = 0; - if (llen >= 2) { - mConfig->language[0] = mLocale[0]; - mConfig->language[1] = mLocale[1]; - } - if (llen >= 5) { - mConfig->country[0] = mLocale[3]; - mConfig->country[1] = mLocale[4]; - } - mConfig->size = sizeof(*mConfig); - - res->setParameters(mConfig); -} - -const ResTable& AssetManager::getResources(bool required) const -{ - const ResTable* rt = getResTable(required); - return *rt; -} - -bool AssetManager::isUpToDate() -{ - AutoMutex _l(mLock); - return mZipSet.isUpToDate(); -} - -void AssetManager::getLocales(Vector<String8>* locales) const -{ - ResTable* res = mResources; - if (res != NULL) { - res->getLocales(locales); - } -} - -/* - * Open a non-asset file as if it were an asset, searching for it in the - * specified app. - * - * Pass in a NULL values for "appName" if the common app directory should - * be used. - */ -Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode mode, - const asset_path& ap) -{ - Asset* pAsset = NULL; - - /* look at the filesystem on disk */ - if (ap.type == kFileTypeDirectory) { - String8 path(ap.path); - path.appendPath(fileName); - - pAsset = openAssetFromFileLocked(path, mode); - - if (pAsset == NULL) { - /* try again, this time with ".gz" */ - path.append(".gz"); - pAsset = openAssetFromFileLocked(path, mode); - } - - if (pAsset != NULL) { - //printf("FOUND NA '%s' on disk\n", fileName); - pAsset->setAssetSource(path); - } - - /* look inside the zip file */ - } else { - String8 path(fileName); - - /* check the appropriate Zip file */ - ZipFileRO* pZip; - ZipEntryRO entry; - - pZip = getZipFileLocked(ap); - if (pZip != NULL) { - //printf("GOT zip, checking NA '%s'\n", (const char*) path); - entry = pZip->findEntryByName(path.string()); - if (entry != NULL) { - //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon); - pAsset = openAssetFromZipLocked(pZip, entry, mode, path); - } - } - - if (pAsset != NULL) { - /* create a "source" name, for debug/display */ - pAsset->setAssetSource( - createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), String8(""), - String8(fileName))); - } - } - - return pAsset; -} - -/* - * Open an asset, searching for it in the directory hierarchy for the - * specified app. - * - * Pass in a NULL values for "appName" if the common app directory should - * be used. - */ -Asset* AssetManager::openInPathLocked(const char* fileName, AccessMode mode, - const asset_path& ap) -{ - Asset* pAsset = NULL; - - /* - * Try various combinations of locale and vendor. - */ - if (mLocale != NULL && mVendor != NULL) - pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, mVendor); - if (pAsset == NULL && mVendor != NULL) - pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, mVendor); - if (pAsset == NULL && mLocale != NULL) - pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, NULL); - if (pAsset == NULL) - pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, NULL); - - return pAsset; -} - -/* - * Open an asset, searching for it in the directory hierarchy for the - * specified locale and vendor. - * - * We also search in "app.jar". - * - * Pass in NULL values for "appName", "locale", and "vendor" if the - * defaults should be used. - */ -Asset* AssetManager::openInLocaleVendorLocked(const char* fileName, AccessMode mode, - const asset_path& ap, const char* locale, const char* vendor) -{ - Asset* pAsset = NULL; - - if (ap.type == kFileTypeDirectory) { - if (mCacheMode == CACHE_OFF) { - /* look at the filesystem on disk */ - String8 path(createPathNameLocked(ap, locale, vendor)); - path.appendPath(fileName); - - String8 excludeName(path); - excludeName.append(kExcludeExtension); - if (::getFileType(excludeName.string()) != kFileTypeNonexistent) { - /* say no more */ - //printf("+++ excluding '%s'\n", (const char*) excludeName); - return kExcludedAsset; - } - - pAsset = openAssetFromFileLocked(path, mode); - - if (pAsset == NULL) { - /* try again, this time with ".gz" */ - path.append(".gz"); - pAsset = openAssetFromFileLocked(path, mode); - } - - if (pAsset != NULL) - pAsset->setAssetSource(path); - } else { - /* find in cache */ - String8 path(createPathNameLocked(ap, locale, vendor)); - path.appendPath(fileName); - - AssetDir::FileInfo tmpInfo; - bool found = false; - - String8 excludeName(path); - excludeName.append(kExcludeExtension); - - if (mCache.indexOf(excludeName) != NAME_NOT_FOUND) { - /* go no farther */ - //printf("+++ Excluding '%s'\n", (const char*) excludeName); - return kExcludedAsset; - } - - /* - * File compression extensions (".gz") don't get stored in the - * name cache, so we have to try both here. - */ - if (mCache.indexOf(path) != NAME_NOT_FOUND) { - found = true; - pAsset = openAssetFromFileLocked(path, mode); - if (pAsset == NULL) { - /* try again, this time with ".gz" */ - path.append(".gz"); - pAsset = openAssetFromFileLocked(path, mode); - } - } - - if (pAsset != NULL) - pAsset->setAssetSource(path); - - /* - * Don't continue the search into the Zip files. Our cached info - * said it was a file on disk; to be consistent with openDir() - * we want to return the loose asset. If the cached file gets - * removed, we fail. - * - * The alternative is to update our cache when files get deleted, - * or make some sort of "best effort" promise, but for now I'm - * taking the hard line. - */ - if (found) { - if (pAsset == NULL) - LOGD("Expected file not found: '%s'\n", path.string()); - return pAsset; - } - } - } - - /* - * Either it wasn't found on disk or on the cached view of the disk. - * Dig through the currently-opened set of Zip files. If caching - * is disabled, the Zip file may get reopened. - */ - if (pAsset == NULL && ap.type == kFileTypeRegular) { - String8 path; - - path.appendPath((locale != NULL) ? locale : kDefaultLocale); - path.appendPath((vendor != NULL) ? vendor : kDefaultVendor); - path.appendPath(fileName); - - /* check the appropriate Zip file */ - ZipFileRO* pZip; - ZipEntryRO entry; - - pZip = getZipFileLocked(ap); - if (pZip != NULL) { - //printf("GOT zip, checking '%s'\n", (const char*) path); - entry = pZip->findEntryByName(path.string()); - if (entry != NULL) { - //printf("FOUND in Zip file for %s/%s-%s\n", - // appName, locale, vendor); - pAsset = openAssetFromZipLocked(pZip, entry, mode, path); - } - } - - if (pAsset != NULL) { - /* create a "source" name, for debug/display */ - pAsset->setAssetSource(createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), - String8(""), String8(fileName))); - } - } - - return pAsset; -} - -/* - * Create a "source name" for a file from a Zip archive. - */ -String8 AssetManager::createZipSourceNameLocked(const String8& zipFileName, - const String8& dirName, const String8& fileName) -{ - String8 sourceName("zip:"); - sourceName.append(zipFileName); - sourceName.append(":"); - if (dirName.length() > 0) { - sourceName.appendPath(dirName); - } - sourceName.appendPath(fileName); - return sourceName; -} - -/* - * Create a path to a loose asset (asset-base/app/locale/vendor). - */ -String8 AssetManager::createPathNameLocked(const asset_path& ap, const char* locale, - const char* vendor) -{ - String8 path(ap.path); - path.appendPath((locale != NULL) ? locale : kDefaultLocale); - path.appendPath((vendor != NULL) ? vendor : kDefaultVendor); - return path; -} - -/* - * Create a path to a loose asset (asset-base/app/rootDir). - */ -String8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir) -{ - String8 path(ap.path); - if (rootDir != NULL) path.appendPath(rootDir); - return path; -} - -/* - * Return a pointer to one of our open Zip archives. Returns NULL if no - * matching Zip file exists. - * - * Right now we have 2 possible Zip files (1 each in app/"common"). - * - * If caching is set to CACHE_OFF, to get the expected behavior we - * need to reopen the Zip file on every request. That would be silly - * and expensive, so instead we just check the file modification date. - * - * Pass in NULL values for "appName", "locale", and "vendor" if the - * generics should be used. - */ -ZipFileRO* AssetManager::getZipFileLocked(const asset_path& ap) -{ - LOGV("getZipFileLocked() in %p\n", this); - - return mZipSet.getZip(ap.path); -} - -/* - * Try to open an asset from a file on disk. - * - * If the file is compressed with gzip, we seek to the start of the - * deflated data and pass that in (just like we would for a Zip archive). - * - * For uncompressed data, we may already have an mmap()ed version sitting - * around. If so, we want to hand that to the Asset instead. - * - * This returns NULL if the file doesn't exist, couldn't be opened, or - * claims to be a ".gz" but isn't. - */ -Asset* AssetManager::openAssetFromFileLocked(const String8& pathName, - AccessMode mode) -{ - Asset* pAsset = NULL; - - if (strcasecmp(pathName.getPathExtension().string(), ".gz") == 0) { - //printf("TRYING '%s'\n", (const char*) pathName); - pAsset = Asset::createFromCompressedFile(pathName.string(), mode); - } else { - //printf("TRYING '%s'\n", (const char*) pathName); - pAsset = Asset::createFromFile(pathName.string(), mode); - } - - return pAsset; -} - -/* - * Given an entry in a Zip archive, create a new Asset object. - * - * If the entry is uncompressed, we may want to create or share a - * slice of shared memory. - */ -Asset* AssetManager::openAssetFromZipLocked(const ZipFileRO* pZipFile, - const ZipEntryRO entry, AccessMode mode, const String8& entryName) -{ - Asset* pAsset = NULL; - - // TODO: look for previously-created shared memory slice? - int method; - long uncompressedLen; - - //printf("USING Zip '%s'\n", pEntry->getFileName()); - - //pZipFile->getEntryInfo(entry, &method, &uncompressedLen, &compressedLen, - // &offset); - if (!pZipFile->getEntryInfo(entry, &method, &uncompressedLen, NULL, NULL, - NULL, NULL)) - { - LOGW("getEntryInfo failed\n"); - return NULL; - } - - FileMap* dataMap = pZipFile->createEntryFileMap(entry); - if (dataMap == NULL) { - LOGW("create map from entry failed\n"); - return NULL; - } - - if (method == ZipFileRO::kCompressStored) { - pAsset = Asset::createFromUncompressedMap(dataMap, mode); - LOGV("Opened uncompressed entry %s in zip %s mode %d: %p", entryName.string(), - dataMap->getFileName(), mode, pAsset); - } else { - pAsset = Asset::createFromCompressedMap(dataMap, method, - uncompressedLen, mode); - LOGV("Opened compressed entry %s in zip %s mode %d: %p", entryName.string(), - dataMap->getFileName(), mode, pAsset); - } - if (pAsset == NULL) { - /* unexpected */ - LOGW("create from segment failed\n"); - } - - return pAsset; -} - - - -/* - * Open a directory in the asset namespace. - * - * An "asset directory" is simply the combination of all files in all - * locations, with ".gz" stripped for loose files. With app, locale, and - * vendor defined, we have 8 directories and 2 Zip archives to scan. - * - * Pass in "" for the root dir. - */ -AssetDir* AssetManager::openDir(const char* dirName) -{ - AutoMutex _l(mLock); - - AssetDir* pDir = NULL; - SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL; - - LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); - assert(dirName != NULL); - - //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase); - - if (mCacheMode != CACHE_OFF && !mCacheValid) - loadFileNameCacheLocked(); - - pDir = new AssetDir; - - /* - * Scan the various directories, merging what we find into a single - * vector. We want to scan them in reverse priority order so that - * the ".EXCLUDE" processing works correctly. Also, if we decide we - * want to remember where the file is coming from, we'll get the right - * version. - * - * We start with Zip archives, then do loose files. - */ - pMergedInfo = new SortedVector<AssetDir::FileInfo>; - - size_t i = mAssetPaths.size(); - while (i > 0) { - i--; - const asset_path& ap = mAssetPaths.itemAt(i); - if (ap.type == kFileTypeRegular) { - LOGV("Adding directory %s from zip %s", dirName, ap.path.string()); - scanAndMergeZipLocked(pMergedInfo, ap, kAssetsRoot, dirName); - } else { - LOGV("Adding directory %s from dir %s", dirName, ap.path.string()); - scanAndMergeDirLocked(pMergedInfo, ap, kAssetsRoot, dirName); - } - } - -#if 0 - printf("FILE LIST:\n"); - for (i = 0; i < (size_t) pMergedInfo->size(); i++) { - printf(" %d: (%d) '%s'\n", i, - pMergedInfo->itemAt(i).getFileType(), - (const char*) pMergedInfo->itemAt(i).getFileName()); - } -#endif - - pDir->setFileList(pMergedInfo); - return pDir; -} - -/* - * Scan the contents of the specified directory and merge them into the - * "pMergedInfo" vector, removing previous entries if we find "exclude" - * directives. - * - * Returns "false" if we found nothing to contribute. - */ -bool AssetManager::scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, - const asset_path& ap, const char* rootDir, const char* dirName) -{ - SortedVector<AssetDir::FileInfo>* pContents; - String8 path; - - assert(pMergedInfo != NULL); - - //printf("scanAndMergeDir: %s %s %s %s\n", appName, locale, vendor,dirName); - - if (mCacheValid) { - int i, start, count; - - pContents = new SortedVector<AssetDir::FileInfo>; - - /* - * Get the basic partial path and find it in the cache. That's - * the start point for the search. - */ - path = createPathNameLocked(ap, rootDir); - if (dirName[0] != '\0') - path.appendPath(dirName); - - start = mCache.indexOf(path); - if (start == NAME_NOT_FOUND) { - //printf("+++ not found in cache: dir '%s'\n", (const char*) path); - delete pContents; - return false; - } - - /* - * The match string looks like "common/default/default/foo/bar/". - * The '/' on the end ensures that we don't match on the directory - * itself or on ".../foo/barfy/". - */ - path.append("/"); - - count = mCache.size(); - - /* - * Pick out the stuff in the current dir by examining the pathname. - * It needs to match the partial pathname prefix, and not have a '/' - * (fssep) anywhere after the prefix. - */ - for (i = start+1; i < count; i++) { - if (mCache[i].getFileName().length() > path.length() && - strncmp(mCache[i].getFileName().string(), path.string(), path.length()) == 0) - { - const char* name = mCache[i].getFileName().string(); - // XXX THIS IS BROKEN! Looks like we need to store the full - // path prefix separately from the file path. - if (strchr(name + path.length(), '/') == NULL) { - /* grab it, reducing path to just the filename component */ - AssetDir::FileInfo tmp = mCache[i]; - tmp.setFileName(tmp.getFileName().getPathLeaf()); - pContents->add(tmp); - } - } else { - /* no longer in the dir or its subdirs */ - break; - } - - } - } else { - path = createPathNameLocked(ap, rootDir); - if (dirName[0] != '\0') - path.appendPath(dirName); - pContents = scanDirLocked(path); - if (pContents == NULL) - return false; - } - - // if we wanted to do an incremental cache fill, we would do it here - - /* - * Process "exclude" directives. If we find a filename that ends with - * ".EXCLUDE", we look for a matching entry in the "merged" set, and - * remove it if we find it. We also delete the "exclude" entry. - */ - int i, count, exclExtLen; - - count = pContents->size(); - exclExtLen = strlen(kExcludeExtension); - for (i = 0; i < count; i++) { - const char* name; - int nameLen; - - name = pContents->itemAt(i).getFileName().string(); - nameLen = strlen(name); - if (nameLen > exclExtLen && - strcmp(name + (nameLen - exclExtLen), kExcludeExtension) == 0) - { - String8 match(name, nameLen - exclExtLen); - int matchIdx; - - matchIdx = AssetDir::FileInfo::findEntry(pMergedInfo, match); - if (matchIdx > 0) { - LOGV("Excluding '%s' [%s]\n", - pMergedInfo->itemAt(matchIdx).getFileName().string(), - pMergedInfo->itemAt(matchIdx).getSourceName().string()); - pMergedInfo->removeAt(matchIdx); - } else { - //printf("+++ no match on '%s'\n", (const char*) match); - } - - LOGD("HEY: size=%d removing %d\n", (int)pContents->size(), i); - pContents->removeAt(i); - i--; // adjust "for" loop - count--; // and loop limit - } - } - - mergeInfoLocked(pMergedInfo, pContents); - - delete pContents; - - return true; -} - -/* - * Scan the contents of the specified directory, and stuff what we find - * into a newly-allocated vector. - * - * Files ending in ".gz" will have their extensions removed. - * - * We should probably think about skipping files with "illegal" names, - * e.g. illegal characters (/\:) or excessive length. - * - * Returns NULL if the specified directory doesn't exist. - */ -SortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& path) -{ - SortedVector<AssetDir::FileInfo>* pContents = NULL; - DIR* dir; - struct dirent* entry; - FileType fileType; - - LOGV("Scanning dir '%s'\n", path.string()); - - dir = opendir(path.string()); - if (dir == NULL) - return NULL; - - pContents = new SortedVector<AssetDir::FileInfo>; - - while (1) { - entry = readdir(dir); - if (entry == NULL) - break; - - if (strcmp(entry->d_name, ".") == 0 || - strcmp(entry->d_name, "..") == 0) - continue; - -#ifdef _DIRENT_HAVE_D_TYPE - if (entry->d_type == DT_REG) - fileType = kFileTypeRegular; - else if (entry->d_type == DT_DIR) - fileType = kFileTypeDirectory; - else - fileType = kFileTypeUnknown; -#else - // stat the file - fileType = ::getFileType(path.appendPathCopy(entry->d_name).string()); -#endif - - if (fileType != kFileTypeRegular && fileType != kFileTypeDirectory) - continue; - - AssetDir::FileInfo info; - info.set(String8(entry->d_name), fileType); - if (strcasecmp(info.getFileName().getPathExtension().string(), ".gz") == 0) - info.setFileName(info.getFileName().getBasePath()); - info.setSourceName(path.appendPathCopy(info.getFileName())); - pContents->add(info); - } - - closedir(dir); - return pContents; -} - -/* - * Scan the contents out of the specified Zip archive, and merge what we - * find into "pMergedInfo". If the Zip archive in question doesn't exist, - * we return immediately. - * - * Returns "false" if we found nothing to contribute. - */ -bool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, - const asset_path& ap, const char* rootDir, const char* baseDirName) -{ - ZipFileRO* pZip; - Vector<String8> dirs; - AssetDir::FileInfo info; - SortedVector<AssetDir::FileInfo> contents; - String8 sourceName, zipName, dirName; - - pZip = mZipSet.getZip(ap.path); - if (pZip == NULL) { - LOGW("Failure opening zip %s\n", ap.path.string()); - return false; - } - - zipName = ZipSet::getPathName(ap.path.string()); - - /* convert "sounds" to "rootDir/sounds" */ - if (rootDir != NULL) dirName = rootDir; - dirName.appendPath(baseDirName); - - /* - * Scan through the list of files, looking for a match. The files in - * the Zip table of contents are not in sorted order, so we have to - * process the entire list. We're looking for a string that begins - * with the characters in "dirName", is followed by a '/', and has no - * subsequent '/' in the stuff that follows. - * - * What makes this especially fun is that directories are not stored - * explicitly in Zip archives, so we have to infer them from context. - * When we see "sounds/foo.wav" we have to leave a note to ourselves - * to insert a directory called "sounds" into the list. We store - * these in temporary vector so that we only return each one once. - * - * Name comparisons are case-sensitive to match UNIX filesystem - * semantics. - */ - int dirNameLen = dirName.length(); - for (int i = 0; i < pZip->getNumEntries(); i++) { - ZipEntryRO entry; - char nameBuf[256]; - - entry = pZip->findEntryByIndex(i); - if (pZip->getEntryFileName(entry, nameBuf, sizeof(nameBuf)) != 0) { - // TODO: fix this if we expect to have long names - LOGE("ARGH: name too long?\n"); - continue; - } - if (dirNameLen == 0 || - (strncmp(nameBuf, dirName.string(), dirNameLen) == 0 && - nameBuf[dirNameLen] == '/')) - { - const char* cp; - const char* nextSlash; - - cp = nameBuf + dirNameLen; - if (dirNameLen != 0) - cp++; // advance past the '/' - - nextSlash = strchr(cp, '/'); -//xxx this may break if there are bare directory entries - if (nextSlash == NULL) { - /* this is a file in the requested directory */ - - info.set(String8(nameBuf).getPathLeaf(), kFileTypeRegular); - - info.setSourceName( - createZipSourceNameLocked(zipName, dirName, info.getFileName())); - - contents.add(info); - //printf("FOUND: file '%s'\n", (const char*) info.mFileName); - } else { - /* this is a subdir; add it if we don't already have it*/ - String8 subdirName(cp, nextSlash - cp); - size_t j; - size_t N = dirs.size(); - - for (j = 0; j < N; j++) { - if (subdirName == dirs[j]) { - break; - } - } - if (j == N) { - dirs.add(subdirName); - } - - //printf("FOUND: dir '%s'\n", (const char*) subdirName); - } - } - } - - /* - * Add the set of unique directories. - */ - for (int i = 0; i < (int) dirs.size(); i++) { - info.set(dirs[i], kFileTypeDirectory); - info.setSourceName( - createZipSourceNameLocked(zipName, dirName, info.getFileName())); - contents.add(info); - } - - mergeInfoLocked(pMergedInfo, &contents); - - return true; -} - - -/* - * Merge two vectors of FileInfo. - * - * The merged contents will be stuffed into *pMergedInfo. - * - * If an entry for a file exists in both "pMergedInfo" and "pContents", - * we use the newer "pContents" entry. - */ -void AssetManager::mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, - const SortedVector<AssetDir::FileInfo>* pContents) -{ - /* - * Merge what we found in this directory with what we found in - * other places. - * - * Two basic approaches: - * (1) Create a new array that holds the unique values of the two - * arrays. - * (2) Take the elements from pContents and shove them into pMergedInfo. - * - * Because these are vectors of complex objects, moving elements around - * inside the vector requires constructing new objects and allocating - * storage for members. With approach #1, we're always adding to the - * end, whereas with #2 we could be inserting multiple elements at the - * front of the vector. Approach #1 requires a full copy of the - * contents of pMergedInfo, but approach #2 requires the same copy for - * every insertion at the front of pMergedInfo. - * - * (We should probably use a SortedVector interface that allows us to - * just stuff items in, trusting us to maintain the sort order.) - */ - SortedVector<AssetDir::FileInfo>* pNewSorted; - int mergeMax, contMax; - int mergeIdx, contIdx; - - pNewSorted = new SortedVector<AssetDir::FileInfo>; - mergeMax = pMergedInfo->size(); - contMax = pContents->size(); - mergeIdx = contIdx = 0; - - while (mergeIdx < mergeMax || contIdx < contMax) { - if (mergeIdx == mergeMax) { - /* hit end of "merge" list, copy rest of "contents" */ - pNewSorted->add(pContents->itemAt(contIdx)); - contIdx++; - } else if (contIdx == contMax) { - /* hit end of "cont" list, copy rest of "merge" */ - pNewSorted->add(pMergedInfo->itemAt(mergeIdx)); - mergeIdx++; - } else if (pMergedInfo->itemAt(mergeIdx) == pContents->itemAt(contIdx)) - { - /* items are identical, add newer and advance both indices */ - pNewSorted->add(pContents->itemAt(contIdx)); - mergeIdx++; - contIdx++; - } else if (pMergedInfo->itemAt(mergeIdx) < pContents->itemAt(contIdx)) - { - /* "merge" is lower, add that one */ - pNewSorted->add(pMergedInfo->itemAt(mergeIdx)); - mergeIdx++; - } else { - /* "cont" is lower, add that one */ - assert(pContents->itemAt(contIdx) < pMergedInfo->itemAt(mergeIdx)); - pNewSorted->add(pContents->itemAt(contIdx)); - contIdx++; - } - } - - /* - * Overwrite the "merged" list with the new stuff. - */ - *pMergedInfo = *pNewSorted; - delete pNewSorted; - -#if 0 // for Vector, rather than SortedVector - int i, j; - for (i = pContents->size() -1; i >= 0; i--) { - bool add = true; - - for (j = pMergedInfo->size() -1; j >= 0; j--) { - /* case-sensitive comparisons, to behave like UNIX fs */ - if (strcmp(pContents->itemAt(i).mFileName, - pMergedInfo->itemAt(j).mFileName) == 0) - { - /* match, don't add this entry */ - add = false; - break; - } - } - - if (add) - pMergedInfo->add(pContents->itemAt(i)); - } -#endif -} - - -/* - * Load all files into the file name cache. We want to do this across - * all combinations of { appname, locale, vendor }, performing a recursive - * directory traversal. - * - * This is not the most efficient data structure. Also, gathering the - * information as we needed it (file-by-file or directory-by-directory) - * would be faster. However, on the actual device, 99% of the files will - * live in Zip archives, so this list will be very small. The trouble - * is that we have to check the "loose" files first, so it's important - * that we don't beat the filesystem silly looking for files that aren't - * there. - * - * Note on thread safety: this is the only function that causes updates - * to mCache, and anybody who tries to use it will call here if !mCacheValid, - * so we need to employ a mutex here. - */ -void AssetManager::loadFileNameCacheLocked(void) -{ - assert(!mCacheValid); - assert(mCache.size() == 0); - -#ifdef DO_TIMINGS // need to link against -lrt for this now - DurationTimer timer; - timer.start(); -#endif - - fncScanLocked(&mCache, ""); - -#ifdef DO_TIMINGS - timer.stop(); - LOGD("Cache scan took %.3fms\n", - timer.durationUsecs() / 1000.0); -#endif - -#if 0 - int i; - printf("CACHED FILE LIST (%d entries):\n", mCache.size()); - for (i = 0; i < (int) mCache.size(); i++) { - printf(" %d: (%d) '%s'\n", i, - mCache.itemAt(i).getFileType(), - (const char*) mCache.itemAt(i).getFileName()); - } -#endif - - mCacheValid = true; -} - -/* - * Scan up to 8 versions of the specified directory. - */ -void AssetManager::fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, - const char* dirName) -{ - size_t i = mAssetPaths.size(); - while (i > 0) { - i--; - const asset_path& ap = mAssetPaths.itemAt(i); - fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, NULL, dirName); - if (mLocale != NULL) - fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, NULL, dirName); - if (mVendor != NULL) - fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, mVendor, dirName); - if (mLocale != NULL && mVendor != NULL) - fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, mVendor, dirName); - } -} - -/* - * Recursively scan this directory and all subdirs. - * - * This is similar to scanAndMergeDir, but we don't remove the .EXCLUDE - * files, and we prepend the extended partial path to the filenames. - */ -bool AssetManager::fncScanAndMergeDirLocked( - SortedVector<AssetDir::FileInfo>* pMergedInfo, - const asset_path& ap, const char* locale, const char* vendor, - const char* dirName) -{ - SortedVector<AssetDir::FileInfo>* pContents; - String8 partialPath; - String8 fullPath; - - // XXX This is broken -- the filename cache needs to hold the base - // asset path separately from its filename. - - partialPath = createPathNameLocked(ap, locale, vendor); - if (dirName[0] != '\0') { - partialPath.appendPath(dirName); - } - - fullPath = partialPath; - pContents = scanDirLocked(fullPath); - if (pContents == NULL) { - return false; // directory did not exist - } - - /* - * Scan all subdirectories of the current dir, merging what we find - * into "pMergedInfo". - */ - for (int i = 0; i < (int) pContents->size(); i++) { - if (pContents->itemAt(i).getFileType() == kFileTypeDirectory) { - String8 subdir(dirName); - subdir.appendPath(pContents->itemAt(i).getFileName()); - - fncScanAndMergeDirLocked(pMergedInfo, ap, locale, vendor, subdir.string()); - } - } - - /* - * To be consistent, we want entries for the root directory. If - * we're the root, add one now. - */ - if (dirName[0] == '\0') { - AssetDir::FileInfo tmpInfo; - - tmpInfo.set(String8(""), kFileTypeDirectory); - tmpInfo.setSourceName(createPathNameLocked(ap, locale, vendor)); - pContents->add(tmpInfo); - } - - /* - * We want to prepend the extended partial path to every entry in - * "pContents". It's the same value for each entry, so this will - * not change the sorting order of the vector contents. - */ - for (int i = 0; i < (int) pContents->size(); i++) { - const AssetDir::FileInfo& info = pContents->itemAt(i); - pContents->editItemAt(i).setFileName(partialPath.appendPathCopy(info.getFileName())); - } - - mergeInfoLocked(pMergedInfo, pContents); - return true; -} - -/* - * Trash the cache. - */ -void AssetManager::purgeFileNameCacheLocked(void) -{ - mCacheValid = false; - mCache.clear(); -} - -/* - * =========================================================================== - * AssetManager::SharedZip - * =========================================================================== - */ - - -Mutex AssetManager::SharedZip::gLock; -DefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen; - -AssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen) - : mPath(path), mZipFile(NULL), mModWhen(modWhen), mResourceTableAsset(NULL) -{ - //LOGI("Creating SharedZip %p %s\n", this, (const char*)mPath); - mZipFile = new ZipFileRO; - LOGV("+++ opening zip '%s'\n", mPath.string()); - if (mZipFile->open(mPath.string()) != NO_ERROR) { - LOGD("failed to open Zip archive '%s'\n", mPath.string()); - delete mZipFile; - mZipFile = NULL; - } -} - -sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path) -{ - AutoMutex _l(gLock); - time_t modWhen = getFileModDate(path); - sp<SharedZip> zip = gOpen.valueFor(path).promote(); - if (zip != NULL && zip->mModWhen == modWhen) { - return zip; - } - zip = new SharedZip(path, modWhen); - gOpen.add(path, zip); - return zip; - -} - -ZipFileRO* AssetManager::SharedZip::getZip() -{ - return mZipFile; -} - -Asset* AssetManager::SharedZip::getResourceTableAsset() -{ - LOGV("Getting from SharedZip %p resource asset %p\n", this, mResourceTableAsset); - return mResourceTableAsset; -} - -Asset* AssetManager::SharedZip::setResourceTableAsset(Asset* asset) -{ - { - AutoMutex _l(gLock); - if (mResourceTableAsset == NULL) { - mResourceTableAsset = asset; - // This is not thread safe the first time it is called, so - // do it here with the global lock held. - asset->getBuffer(true); - return asset; - } - } - delete asset; - return mResourceTableAsset; -} - -bool AssetManager::SharedZip::isUpToDate() -{ - time_t modWhen = getFileModDate(mPath.string()); - return mModWhen == modWhen; -} - -AssetManager::SharedZip::~SharedZip() -{ - //LOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath); - if (mResourceTableAsset != NULL) { - delete mResourceTableAsset; - } - if (mZipFile != NULL) { - delete mZipFile; - LOGV("Closed '%s'\n", mPath.string()); - } -} - -/* - * =========================================================================== - * AssetManager::ZipSet - * =========================================================================== - */ - -/* - * Constructor. - */ -AssetManager::ZipSet::ZipSet(void) -{ -} - -/* - * Destructor. Close any open archives. - */ -AssetManager::ZipSet::~ZipSet(void) -{ - size_t N = mZipFile.size(); - for (size_t i = 0; i < N; i++) - closeZip(i); -} - -/* - * Close a Zip file and reset the entry. - */ -void AssetManager::ZipSet::closeZip(int idx) -{ - mZipFile.editItemAt(idx) = NULL; -} - - -/* - * Retrieve the appropriate Zip file from the set. - */ -ZipFileRO* AssetManager::ZipSet::getZip(const String8& path) -{ - int idx = getIndex(path); - sp<SharedZip> zip = mZipFile[idx]; - if (zip == NULL) { - zip = SharedZip::get(path); - mZipFile.editItemAt(idx) = zip; - } - return zip->getZip(); -} - -Asset* AssetManager::ZipSet::getZipResourceTable(const String8& path) -{ - int idx = getIndex(path); - sp<SharedZip> zip = mZipFile[idx]; - if (zip == NULL) { - zip = SharedZip::get(path); - mZipFile.editItemAt(idx) = zip; - } - return zip->getResourceTableAsset(); -} - -Asset* AssetManager::ZipSet::setZipResourceTable(const String8& path, - Asset* asset) -{ - int idx = getIndex(path); - sp<SharedZip> zip = mZipFile[idx]; - // doesn't make sense to call before previously accessing. - return zip->setResourceTableAsset(asset); -} - -/* - * Generate the partial pathname for the specified archive. The caller - * gets to prepend the asset root directory. - * - * Returns something like "common/en-US-noogle.jar". - */ -/*static*/ String8 AssetManager::ZipSet::getPathName(const char* zipPath) -{ - return String8(zipPath); -} - -bool AssetManager::ZipSet::isUpToDate() -{ - const size_t N = mZipFile.size(); - for (size_t i=0; i<N; i++) { - if (mZipFile[i] != NULL && !mZipFile[i]->isUpToDate()) { - return false; - } - } - return true; -} - -/* - * Compute the zip file's index. - * - * "appName", "locale", and "vendor" should be set to NULL to indicate the - * default directory. - */ -int AssetManager::ZipSet::getIndex(const String8& zip) const -{ - const size_t N = mZipPath.size(); - for (size_t i=0; i<N; i++) { - if (mZipPath[i] == zip) { - return i; - } - } - - mZipPath.add(zip); - mZipFile.add(NULL); - - return mZipPath.size()-1; -} - diff --git a/libs/utils/Binder.cpp b/libs/utils/Binder.cpp deleted file mode 100644 index 37e4685..0000000 --- a/libs/utils/Binder.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/Binder.h> - -#include <utils/Atomic.h> -#include <utils/BpBinder.h> -#include <utils/IInterface.h> -#include <utils/Parcel.h> - -#include <stdio.h> - -namespace android { - -// --------------------------------------------------------------------------- - -sp<IInterface> IBinder::queryLocalInterface(const String16& descriptor) -{ - return NULL; -} - -BBinder* IBinder::localBinder() -{ - return NULL; -} - -BpBinder* IBinder::remoteBinder() -{ - return NULL; -} - -bool IBinder::checkSubclass(const void* /*subclassID*/) const -{ - return false; -} - -// --------------------------------------------------------------------------- - -class BBinder::Extras -{ -public: - Mutex mLock; - BpBinder::ObjectManager mObjects; -}; - -// --------------------------------------------------------------------------- - -BBinder::BBinder() - : mExtras(NULL) -{ -} - -bool BBinder::isBinderAlive() const -{ - return true; -} - -status_t BBinder::pingBinder() -{ - return NO_ERROR; -} - -String16 BBinder::getInterfaceDescriptor() const -{ - LOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this); - return String16(); -} - -status_t BBinder::transact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - data.setDataPosition(0); - - status_t err = NO_ERROR; - switch (code) { - case PING_TRANSACTION: - reply->writeInt32(pingBinder()); - break; - default: - err = onTransact(code, data, reply, flags); - break; - } - - if (reply != NULL) { - reply->setDataPosition(0); - } - - return err; -} - -status_t BBinder::linkToDeath( - const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags) -{ - return INVALID_OPERATION; -} - -status_t BBinder::unlinkToDeath( - const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags, - wp<DeathRecipient>* outRecipient) -{ - return INVALID_OPERATION; -} - -status_t BBinder::dump(int fd, const Vector<String16>& args) -{ - return NO_ERROR; -} - -void BBinder::attachObject( - const void* objectID, void* object, void* cleanupCookie, - object_cleanup_func func) -{ - Extras* e = mExtras; - - if (!e) { - e = new Extras; - if (android_atomic_cmpxchg(0, reinterpret_cast<int32_t>(e), - reinterpret_cast<volatile int32_t*>(&mExtras)) != 0) { - delete e; - e = mExtras; - } - if (e == 0) return; // out of memory - } - - AutoMutex _l(e->mLock); - e->mObjects.attach(objectID, object, cleanupCookie, func); -} - -void* BBinder::findObject(const void* objectID) const -{ - Extras* e = mExtras; - if (!e) return NULL; - - AutoMutex _l(e->mLock); - return e->mObjects.find(objectID); -} - -void BBinder::detachObject(const void* objectID) -{ - Extras* e = mExtras; - if (!e) return; - - AutoMutex _l(e->mLock); - e->mObjects.detach(objectID); -} - -BBinder* BBinder::localBinder() -{ - return this; -} - -BBinder::~BBinder() -{ - if (mExtras) delete mExtras; -} - - -status_t BBinder::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch (code) { - case INTERFACE_TRANSACTION: - reply->writeString16(getInterfaceDescriptor()); - return NO_ERROR; - - case DUMP_TRANSACTION: { - int fd = data.readFileDescriptor(); - int argc = data.readInt32(); - Vector<String16> args; - for (int i = 0; i < argc && data.dataAvail() > 0; i++) { - args.add(data.readString16()); - } - return dump(fd, args); - } - default: - return UNKNOWN_TRANSACTION; - } -} - -// --------------------------------------------------------------------------- - -enum { - // This is used to transfer ownership of the remote binder from - // the BpRefBase object holding it (when it is constructed), to the - // owner of the BpRefBase object when it first acquires that BpRefBase. - kRemoteAcquired = 0x00000001 -}; - -BpRefBase::BpRefBase(const sp<IBinder>& o) - : mRemote(o.get()), mRefs(NULL), mState(0) -{ - extendObjectLifetime(OBJECT_LIFETIME_WEAK); - - if (mRemote) { - mRemote->incStrong(this); // Removed on first IncStrong(). - mRefs = mRemote->createWeak(this); // Held for our entire lifetime. - } -} - -BpRefBase::~BpRefBase() -{ - if (mRemote) { - if (!(mState&kRemoteAcquired)) { - mRemote->decStrong(this); - } - mRefs->decWeak(this); - } -} - -void BpRefBase::onFirstRef() -{ - android_atomic_or(kRemoteAcquired, &mState); -} - -void BpRefBase::onLastStrongRef(const void* id) -{ - if (mRemote) { - mRemote->decStrong(this); - } -} - -bool BpRefBase::onIncStrongAttempted(uint32_t flags, const void* id) -{ - return mRemote ? mRefs->attemptIncStrong(this) : false; -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/utils/BpBinder.cpp b/libs/utils/BpBinder.cpp deleted file mode 100644 index 69ab195..0000000 --- a/libs/utils/BpBinder.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "BpBinder" -//#define LOG_NDEBUG 0 - -#include <utils/BpBinder.h> - -#include <utils/IPCThreadState.h> -#include <utils/Log.h> - -#include <stdio.h> - -//#undef LOGV -//#define LOGV(...) fprintf(stderr, __VA_ARGS__) - -namespace android { - -// --------------------------------------------------------------------------- - -BpBinder::ObjectManager::ObjectManager() -{ -} - -BpBinder::ObjectManager::~ObjectManager() -{ - kill(); -} - -void BpBinder::ObjectManager::attach( - const void* objectID, void* object, void* cleanupCookie, - IBinder::object_cleanup_func func) -{ - entry_t e; - e.object = object; - e.cleanupCookie = cleanupCookie; - e.func = func; - - if (mObjects.indexOfKey(objectID) >= 0) { - LOGE("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object ID already in use", - objectID, this, object); - return; - } - - mObjects.add(objectID, e); -} - -void* BpBinder::ObjectManager::find(const void* objectID) const -{ - const ssize_t i = mObjects.indexOfKey(objectID); - if (i < 0) return NULL; - return mObjects.valueAt(i).object; -} - -void BpBinder::ObjectManager::detach(const void* objectID) -{ - mObjects.removeItem(objectID); -} - -void BpBinder::ObjectManager::kill() -{ - const size_t N = mObjects.size(); - LOGV("Killing %d objects in manager %p", N, this); - for (size_t i=0; i<N; i++) { - const entry_t& e = mObjects.valueAt(i); - if (e.func != NULL) { - e.func(mObjects.keyAt(i), e.object, e.cleanupCookie); - } - } - - mObjects.clear(); -} - -// --------------------------------------------------------------------------- - -BpBinder::BpBinder(int32_t handle) - : mHandle(handle) - , mAlive(1) - , mObitsSent(0) - , mObituaries(NULL) -{ - LOGV("Creating BpBinder %p handle %d\n", this, mHandle); - - extendObjectLifetime(OBJECT_LIFETIME_WEAK); - IPCThreadState::self()->incWeakHandle(handle); -} - -String16 BpBinder::getInterfaceDescriptor() const -{ - String16 res; - Parcel send, reply; - status_t err = const_cast<BpBinder*>(this)->transact( - INTERFACE_TRANSACTION, send, &reply); - if (err == NO_ERROR) { - res = reply.readString16(); - } - return res; -} - -bool BpBinder::isBinderAlive() const -{ - return mAlive != 0; -} - -status_t BpBinder::pingBinder() -{ - Parcel send; - Parcel reply; - status_t err = transact(PING_TRANSACTION, send, &reply); - if (err != NO_ERROR) return err; - if (reply.dataSize() < sizeof(status_t)) return NOT_ENOUGH_DATA; - return (status_t)reply.readInt32(); -} - -status_t BpBinder::dump(int fd, const Vector<String16>& args) -{ - Parcel send; - Parcel reply; - send.writeFileDescriptor(fd); - const size_t numArgs = args.size(); - send.writeInt32(numArgs); - for (size_t i = 0; i < numArgs; i++) { - send.writeString16(args[i]); - } - status_t err = transact(DUMP_TRANSACTION, send, &reply); - return err; -} - -status_t BpBinder::transact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - // Once a binder has died, it will never come back to life. - if (mAlive) { - status_t status = IPCThreadState::self()->transact( - mHandle, code, data, reply, flags); - if (status == DEAD_OBJECT) mAlive = 0; - return status; - } - - return DEAD_OBJECT; -} - -status_t BpBinder::linkToDeath( - const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags) -{ - Obituary ob; - ob.recipient = recipient; - ob.cookie = cookie; - ob.flags = flags; - - LOG_ALWAYS_FATAL_IF(recipient == NULL, - "linkToDeath(): recipient must be non-NULL"); - - { - AutoMutex _l(mLock); - - if (!mObitsSent) { - if (!mObituaries) { - mObituaries = new Vector<Obituary>; - if (!mObituaries) { - return NO_MEMORY; - } - LOGV("Requesting death notification: %p handle %d\n", this, mHandle); - getWeakRefs()->incWeak(this); - IPCThreadState* self = IPCThreadState::self(); - self->requestDeathNotification(mHandle, this); - self->flushCommands(); - } - ssize_t res = mObituaries->add(ob); - return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res; - } - } - - return DEAD_OBJECT; -} - -status_t BpBinder::unlinkToDeath( - const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags, - wp<DeathRecipient>* outRecipient) -{ - AutoMutex _l(mLock); - - if (mObitsSent) { - return DEAD_OBJECT; - } - - const size_t N = mObituaries ? mObituaries->size() : 0; - for (size_t i=0; i<N; i++) { - const Obituary& obit = mObituaries->itemAt(i); - if ((obit.recipient == recipient - || (recipient == NULL && obit.cookie == cookie)) - && obit.flags == flags) { - const uint32_t allFlags = obit.flags|flags; - if (outRecipient != NULL) { - *outRecipient = mObituaries->itemAt(i).recipient; - } - mObituaries->removeAt(i); - if (mObituaries->size() == 0) { - LOGV("Clearing death notification: %p handle %d\n", this, mHandle); - IPCThreadState* self = IPCThreadState::self(); - self->clearDeathNotification(mHandle, this); - self->flushCommands(); - delete mObituaries; - mObituaries = NULL; - } - return NO_ERROR; - } - } - - return NAME_NOT_FOUND; -} - -void BpBinder::sendObituary() -{ - LOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n", - this, mHandle, mObitsSent ? "true" : "false"); - - mAlive = 0; - if (mObitsSent) return; - - mLock.lock(); - Vector<Obituary>* obits = mObituaries; - if(obits != NULL) { - LOGV("Clearing sent death notification: %p handle %d\n", this, mHandle); - IPCThreadState* self = IPCThreadState::self(); - self->clearDeathNotification(mHandle, this); - self->flushCommands(); - mObituaries = NULL; - } - mObitsSent = 1; - mLock.unlock(); - - LOGV("Reporting death of proxy %p for %d recipients\n", - this, obits ? obits->size() : 0); - - if (obits != NULL) { - const size_t N = obits->size(); - for (size_t i=0; i<N; i++) { - reportOneDeath(obits->itemAt(i)); - } - - delete obits; - } -} - -void BpBinder::reportOneDeath(const Obituary& obit) -{ - sp<DeathRecipient> recipient = obit.recipient.promote(); - LOGV("Reporting death to recipient: %p\n", recipient.get()); - if (recipient == NULL) return; - - recipient->binderDied(this); -} - - -void BpBinder::attachObject( - const void* objectID, void* object, void* cleanupCookie, - object_cleanup_func func) -{ - AutoMutex _l(mLock); - LOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects); - mObjects.attach(objectID, object, cleanupCookie, func); -} - -void* BpBinder::findObject(const void* objectID) const -{ - AutoMutex _l(mLock); - return mObjects.find(objectID); -} - -void BpBinder::detachObject(const void* objectID) -{ - AutoMutex _l(mLock); - mObjects.detach(objectID); -} - -BpBinder* BpBinder::remoteBinder() -{ - return this; -} - -BpBinder::~BpBinder() -{ - LOGV("Destroying BpBinder %p handle %d\n", this, mHandle); - - IPCThreadState* ipc = IPCThreadState::self(); - - mLock.lock(); - Vector<Obituary>* obits = mObituaries; - if(obits != NULL) { - if (ipc) ipc->clearDeathNotification(mHandle, this); - mObituaries = NULL; - } - mLock.unlock(); - - if (obits != NULL) { - // XXX Should we tell any remaining DeathRecipient - // objects that the last strong ref has gone away, so they - // are no longer linked? - delete obits; - } - - if (ipc) { - ipc->expungeHandle(mHandle, this); - ipc->decWeakHandle(mHandle); - } -} - -void BpBinder::onFirstRef() -{ - LOGV("onFirstRef BpBinder %p handle %d\n", this, mHandle); - IPCThreadState* ipc = IPCThreadState::self(); - if (ipc) ipc->incStrongHandle(mHandle); -} - -void BpBinder::onLastStrongRef(const void* id) -{ - LOGV("onLastStrongRef BpBinder %p handle %d\n", this, mHandle); - IF_LOGV() { - printRefs(); - } - IPCThreadState* ipc = IPCThreadState::self(); - if (ipc) ipc->decStrongHandle(mHandle); -} - -bool BpBinder::onIncStrongAttempted(uint32_t flags, const void* id) -{ - LOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, mHandle); - IPCThreadState* ipc = IPCThreadState::self(); - return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false; -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/utils/BufferedTextOutput.cpp b/libs/utils/BufferedTextOutput.cpp deleted file mode 100644 index 989662e..0000000 --- a/libs/utils/BufferedTextOutput.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/BufferedTextOutput.h> - -#include <utils/Atomic.h> -#include <utils/Debug.h> -#include <utils/Log.h> -#include <utils/RefBase.h> -#include <utils/Vector.h> -#include <cutils/threads.h> - -#include <private/utils/Static.h> - -#include <stdio.h> -#include <stdlib.h> - -// --------------------------------------------------------------------------- - -namespace android { - -struct BufferedTextOutput::BufferState : public RefBase -{ - BufferState(int32_t _seq) - : seq(_seq) - , buffer(NULL) - , bufferPos(0) - , bufferSize(0) - , atFront(true) - , indent(0) - , bundle(0) { - } - ~BufferState() { - free(buffer); - } - - status_t append(const char* txt, size_t len) { - if ((len+bufferPos) > bufferSize) { - void* b = realloc(buffer, ((len+bufferPos)*3)/2); - if (!b) return NO_MEMORY; - buffer = (char*)b; - } - memcpy(buffer+bufferPos, txt, len); - bufferPos += len; - return NO_ERROR; - } - - void restart() { - bufferPos = 0; - atFront = true; - if (bufferSize > 256) { - void* b = realloc(buffer, 256); - if (b) { - buffer = (char*)b; - bufferSize = 256; - } - } - } - - const int32_t seq; - char* buffer; - size_t bufferPos; - size_t bufferSize; - bool atFront; - int32_t indent; - int32_t bundle; -}; - -struct BufferedTextOutput::ThreadState -{ - Vector<sp<BufferedTextOutput::BufferState> > states; -}; - -static mutex_t gMutex; - -static thread_store_t tls; - -BufferedTextOutput::ThreadState* BufferedTextOutput::getThreadState() -{ - ThreadState* ts = (ThreadState*) thread_store_get( &tls ); - if (ts) return ts; - ts = new ThreadState; - thread_store_set( &tls, ts, threadDestructor ); - return ts; -} - -void BufferedTextOutput::threadDestructor(void *st) -{ - delete ((ThreadState*)st); -} - -static volatile int32_t gSequence = 0; - -static volatile int32_t gFreeBufferIndex = -1; - -static int32_t allocBufferIndex() -{ - int32_t res = -1; - - mutex_lock(&gMutex); - - if (gFreeBufferIndex >= 0) { - res = gFreeBufferIndex; - gFreeBufferIndex = gTextBuffers[res]; - gTextBuffers.editItemAt(res) = -1; - - } else { - res = gTextBuffers.size(); - gTextBuffers.add(-1); - } - - mutex_unlock(&gMutex); - - return res; -} - -static void freeBufferIndex(int32_t idx) -{ - mutex_lock(&gMutex); - gTextBuffers.editItemAt(idx) = gFreeBufferIndex; - gFreeBufferIndex = idx; - mutex_unlock(&gMutex); -} - -// --------------------------------------------------------------------------- - -BufferedTextOutput::BufferedTextOutput(uint32_t flags) - : mFlags(flags) - , mSeq(android_atomic_inc(&gSequence)) - , mIndex(allocBufferIndex()) -{ - mGlobalState = new BufferState(mSeq); - if (mGlobalState) mGlobalState->incStrong(this); -} - -BufferedTextOutput::~BufferedTextOutput() -{ - if (mGlobalState) mGlobalState->decStrong(this); - freeBufferIndex(mIndex); -} - -status_t BufferedTextOutput::print(const char* txt, size_t len) -{ - //printf("BufferedTextOutput: printing %d\n", len); - - AutoMutex _l(mLock); - BufferState* b = getBuffer(); - - const char* const end = txt+len; - - status_t err; - - while (txt < end) { - // Find the next line. - const char* first = txt; - while (txt < end && *txt != '\n') txt++; - - // Include this and all following empty lines. - while (txt < end && *txt == '\n') txt++; - - // Special cases for first data on a line. - if (b->atFront) { - if (b->indent > 0) { - // If this is the start of a line, add the indent. - const char* prefix = stringForIndent(b->indent); - err = b->append(prefix, strlen(prefix)); - if (err != NO_ERROR) return err; - - } else if (*(txt-1) == '\n' && !b->bundle) { - // Fast path: if we are not indenting or bundling, and - // have been given one or more complete lines, just write - // them out without going through the buffer. - - // Slurp up all of the lines. - const char* lastLine = txt+1; - while (txt < end) { - if (*txt++ == '\n') lastLine = txt; - } - struct iovec vec; - vec.iov_base = (void*)first; - vec.iov_len = lastLine-first; - //printf("Writing %d bytes of data!\n", vec.iov_len); - writeLines(vec, 1); - txt = lastLine; - continue; - } - } - - // Append the new text to the buffer. - err = b->append(first, txt-first); - if (err != NO_ERROR) return err; - b->atFront = *(txt-1) == '\n'; - - // If we have finished a line and are not bundling, write - // it out. - //printf("Buffer is now %d bytes\n", b->bufferPos); - if (b->atFront && !b->bundle) { - struct iovec vec; - vec.iov_base = b->buffer; - vec.iov_len = b->bufferPos; - //printf("Writing %d bytes of data!\n", vec.iov_len); - writeLines(vec, 1); - b->restart(); - } - } - - return NO_ERROR; -} - -void BufferedTextOutput::moveIndent(int delta) -{ - AutoMutex _l(mLock); - BufferState* b = getBuffer(); - b->indent += delta; - if (b->indent < 0) b->indent = 0; -} - -void BufferedTextOutput::pushBundle() -{ - AutoMutex _l(mLock); - BufferState* b = getBuffer(); - b->bundle++; -} - -void BufferedTextOutput::popBundle() -{ - AutoMutex _l(mLock); - BufferState* b = getBuffer(); - b->bundle--; - LOG_FATAL_IF(b->bundle < 0, - "TextOutput::popBundle() called more times than pushBundle()"); - if (b->bundle < 0) b->bundle = 0; - - if (b->bundle == 0) { - // Last bundle, write out data if it is complete. If it is not - // complete, don't write until the last line is done... this may - // or may not be the write thing to do, but it's the easiest. - if (b->bufferPos > 0 && b->atFront) { - struct iovec vec; - vec.iov_base = b->buffer; - vec.iov_len = b->bufferPos; - writeLines(vec, 1); - b->restart(); - } - } -} - -BufferedTextOutput::BufferState* BufferedTextOutput::getBuffer() const -{ - if ((mFlags&MULTITHREADED) != 0) { - ThreadState* ts = getThreadState(); - if (ts) { - while (ts->states.size() <= (size_t)mIndex) ts->states.add(NULL); - BufferState* bs = ts->states[mIndex].get(); - if (bs != NULL && bs->seq == mSeq) return bs; - - ts->states.editItemAt(mIndex) = new BufferState(mIndex); - bs = ts->states[mIndex].get(); - if (bs != NULL) return bs; - } - } - - return mGlobalState; -} - -}; // namespace android diff --git a/libs/utils/CallStack.cpp b/libs/utils/CallStack.cpp deleted file mode 100644 index 26fb22a..0000000 --- a/libs/utils/CallStack.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "CallStack" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#if HAVE_DLADDR -#include <dlfcn.h> -#endif - -#if HAVE_CXXABI -#include <cxxabi.h> -#endif - -#include <unwind.h> - -#include <utils/Log.h> -#include <utils/Errors.h> -#include <utils/CallStack.h> -#include <utils/threads.h> - - -/*****************************************************************************/ -namespace android { - - -typedef struct { - size_t count; - size_t ignore; - const void** addrs; -} stack_crawl_state_t; - -static -_Unwind_Reason_Code trace_function(_Unwind_Context *context, void *arg) -{ - stack_crawl_state_t* state = (stack_crawl_state_t*)arg; - if (state->count) { - void* ip = (void*)_Unwind_GetIP(context); - if (ip) { - if (state->ignore) { - state->ignore--; - } else { - state->addrs[0] = ip; - state->addrs++; - state->count--; - } - } - } - return _URC_NO_REASON; -} - -static -int backtrace(const void** addrs, size_t ignore, size_t size) -{ - stack_crawl_state_t state; - state.count = size; - state.ignore = ignore; - state.addrs = addrs; - _Unwind_Backtrace(trace_function, (void*)&state); - return size - state.count; -} - -/*****************************************************************************/ - -static -const char *lookup_symbol(const void* addr, void **offset, char* name, size_t bufSize) -{ -#if HAVE_DLADDR - Dl_info info; - if (dladdr(addr, &info)) { - *offset = info.dli_saddr; - return info.dli_sname; - } -#endif - return NULL; -} - -static -int32_t linux_gcc_demangler(const char *mangled_name, char *unmangled_name, size_t buffersize) -{ - size_t out_len = 0; -#if HAVE_CXXABI - int status = 0; - char *demangled = abi::__cxa_demangle(mangled_name, 0, &out_len, &status); - if (status == 0) { - // OK - if (out_len < buffersize) memcpy(unmangled_name, demangled, out_len); - else out_len = 0; - free(demangled); - } else { - out_len = 0; - } -#endif - return out_len; -} - -/*****************************************************************************/ - -class MapInfo { - struct mapinfo { - struct mapinfo *next; - uint64_t start; - uint64_t end; - char name[]; - }; - - const char *map_to_name(uint64_t pc, const char* def) { - mapinfo* mi = getMapInfoList(); - while(mi) { - if ((pc >= mi->start) && (pc < mi->end)) - return mi->name; - mi = mi->next; - } - return def; - } - - mapinfo *parse_maps_line(char *line) { - mapinfo *mi; - int len = strlen(line); - if (len < 1) return 0; - line[--len] = 0; - if (len < 50) return 0; - if (line[20] != 'x') return 0; - mi = (mapinfo*)malloc(sizeof(mapinfo) + (len - 47)); - if (mi == 0) return 0; - mi->start = strtoull(line, 0, 16); - mi->end = strtoull(line + 9, 0, 16); - mi->next = 0; - strcpy(mi->name, line + 49); - return mi; - } - - mapinfo* getMapInfoList() { - Mutex::Autolock _l(mLock); - if (milist == 0) { - char data[1024]; - FILE *fp; - sprintf(data, "/proc/%d/maps", getpid()); - fp = fopen(data, "r"); - if (fp) { - while(fgets(data, 1024, fp)) { - mapinfo *mi = parse_maps_line(data); - if(mi) { - mi->next = milist; - milist = mi; - } - } - fclose(fp); - } - } - return milist; - } - mapinfo* milist; - Mutex mLock; - static MapInfo sMapInfo; - -public: - MapInfo() - : milist(0) { - } - - ~MapInfo() { - while (milist) { - mapinfo *next = milist->next; - free(milist); - milist = next; - } - } - - static const char *mapAddressToName(const void* pc, const char* def) { - return sMapInfo.map_to_name((uint64_t)pc, def); - } - -}; - -/*****************************************************************************/ - -MapInfo MapInfo::sMapInfo; - -/*****************************************************************************/ - -CallStack::CallStack() - : mCount(0) -{ -} - -CallStack::CallStack(const CallStack& rhs) - : mCount(rhs.mCount) -{ - if (mCount) { - memcpy(mStack, rhs.mStack, mCount*sizeof(void*)); - } -} - -CallStack::~CallStack() -{ -} - -CallStack& CallStack::operator = (const CallStack& rhs) -{ - mCount = rhs.mCount; - if (mCount) { - memcpy(mStack, rhs.mStack, mCount*sizeof(void*)); - } - return *this; -} - -bool CallStack::operator == (const CallStack& rhs) const { - if (mCount != rhs.mCount) - return false; - return !mCount || (memcmp(mStack, rhs.mStack, mCount*sizeof(void*)) == 0); -} - -bool CallStack::operator != (const CallStack& rhs) const { - return !operator == (rhs); -} - -bool CallStack::operator < (const CallStack& rhs) const { - if (mCount != rhs.mCount) - return mCount < rhs.mCount; - return memcmp(mStack, rhs.mStack, mCount*sizeof(void*)) < 0; -} - -bool CallStack::operator >= (const CallStack& rhs) const { - return !operator < (rhs); -} - -bool CallStack::operator > (const CallStack& rhs) const { - if (mCount != rhs.mCount) - return mCount > rhs.mCount; - return memcmp(mStack, rhs.mStack, mCount*sizeof(void*)) > 0; -} - -bool CallStack::operator <= (const CallStack& rhs) const { - return !operator > (rhs); -} - -const void* CallStack::operator [] (int index) const { - if (index >= int(mCount)) - return 0; - return mStack[index]; -} - - -void CallStack::clear() -{ - mCount = 0; -} - -void CallStack::update(int32_t ignoreDepth, int32_t maxDepth) -{ - if (maxDepth > MAX_DEPTH) - maxDepth = MAX_DEPTH; - mCount = backtrace(mStack, ignoreDepth, maxDepth); -} - -// Return the stack frame name on the designated level -String8 CallStack::toStringSingleLevel(const char* prefix, int32_t level) const -{ - String8 res; - char namebuf[1024]; - char tmp[256]; - char tmp1[32]; - char tmp2[32]; - void *offs; - - const void* ip = mStack[level]; - if (!ip) return res; - - if (prefix) res.append(prefix); - snprintf(tmp1, 32, "#%02d ", level); - res.append(tmp1); - - const char* name = lookup_symbol(ip, &offs, namebuf, sizeof(namebuf)); - if (name) { - if (linux_gcc_demangler(name, tmp, 256) != 0) - name = tmp; - snprintf(tmp1, 32, "0x%p: <", ip); - snprintf(tmp2, 32, ">+0x%p", offs); - res.append(tmp1); - res.append(name); - res.append(tmp2); - } else { - name = MapInfo::mapAddressToName(ip, "<unknown>"); - snprintf(tmp, 256, "pc %p %s", ip, name); - res.append(tmp); - } - res.append("\n"); - - return res; -} - -// Dump a stack trace to the log -void CallStack::dump(const char* prefix) const -{ - /* - * Sending a single long log may be truncated since the stack levels can - * get very deep. So we request function names of each frame individually. - */ - for (int i=0; i<int(mCount); i++) { - LOGD("%s", toStringSingleLevel(prefix, i).string()); - } -} - -// Return a string (possibly very long) containing the complete stack trace -String8 CallStack::toString(const char* prefix) const -{ - String8 res; - - for (int i=0; i<int(mCount); i++) { - res.append(toStringSingleLevel(prefix, i).string()); - } - - return res; -} - -/*****************************************************************************/ - -}; // namespace android diff --git a/libs/utils/Debug.cpp b/libs/utils/Debug.cpp deleted file mode 100644 index f7988ec..0000000 --- a/libs/utils/Debug.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/Debug.h> - -#include <utils/misc.h> - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> - -namespace android { - -// --------------------------------------------------------------------- - -static const char indentStr[] = -" " -" "; - -const char* stringForIndent(int32_t indentLevel) -{ - ssize_t off = sizeof(indentStr)-1-(indentLevel*2); - return indentStr + (off < 0 ? 0 : off); -} - -// --------------------------------------------------------------------- - -static void defaultPrintFunc(void* cookie, const char* txt) -{ - printf("%s", txt); -} - -// --------------------------------------------------------------------- - -static inline int isident(int c) -{ - return isalnum(c) || c == '_'; -} - -static inline bool isasciitype(char c) -{ - if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true; - return false; -} - -static inline char makehexdigit(uint32_t val) -{ - return "0123456789abcdef"[val&0xF]; -} - -static char* appendhexnum(uint32_t val, char* out) -{ - for( int32_t i=28; i>=0; i-=4 ) { - *out++ = makehexdigit( val>>i ); - } - *out = 0; - return out; -} - -static inline char makeupperhexdigit(uint32_t val) -{ - return "0123456789ABCDEF"[val&0xF]; -} - -static char* appendupperhexnum(uint32_t val, char* out) -{ - for( int32_t i=28; i>=0; i-=4 ) { - *out++ = makeupperhexdigit( val>>i ); - } - *out = 0; - return out; -} - -static char* appendcharornum(char c, char* out, bool skipzero = true) -{ - if (skipzero && c == 0) return out; - - if (isasciitype(c)) { - *out++ = c; - return out; - } - - *out++ = '\\'; - *out++ = 'x'; - *out++ = makehexdigit(c>>4); - *out++ = makehexdigit(c); - return out; -} - -static char* typetostring(uint32_t type, char* out, - bool fullContext = true, - bool strict = false) -{ - char* pos = out; - char c[4]; - c[0] = (char)((type>>24)&0xFF); - c[1] = (char)((type>>16)&0xFF); - c[2] = (char)((type>>8)&0xFF); - c[3] = (char)(type&0xFF); - bool valid; - if( !strict ) { - // now even less strict! - // valid = isasciitype(c[3]); - valid = true; - int32_t i = 0; - bool zero = true; - while (valid && i<3) { - if (c[i] == 0) { - if (!zero) valid = false; - } else { - zero = false; - //if (!isasciitype(c[i])) valid = false; - } - i++; - } - // if all zeros, not a valid type code. - if (zero) valid = false; - } else { - valid = isident(c[3]) ? true : false; - int32_t i = 0; - bool zero = true; - while (valid && i<3) { - if (c[i] == 0) { - if (!zero) valid = false; - } else { - zero = false; - if (!isident(c[i])) valid = false; - } - i++; - } - } - if( valid && (!fullContext || c[0] != '0' || c[1] != 'x') ) { - if( fullContext ) *pos++ = '\''; - pos = appendcharornum(c[0], pos); - pos = appendcharornum(c[1], pos); - pos = appendcharornum(c[2], pos); - pos = appendcharornum(c[3], pos); - if( fullContext ) *pos++ = '\''; - *pos = 0; - return pos; - } - - if( fullContext ) { - *pos++ = '0'; - *pos++ = 'x'; - } - return appendhexnum(type, pos); -} - -void printTypeCode(uint32_t typeCode, debugPrintFunc func, void* cookie) -{ - char buffer[32]; - char* end = typetostring(typeCode, buffer); - *end = 0; - func ? (*func)(cookie, buffer) : defaultPrintFunc(cookie, buffer); -} - -void printHexData(int32_t indent, const void *buf, size_t length, - size_t bytesPerLine, int32_t singleLineBytesCutoff, - size_t alignment, bool cStyle, - debugPrintFunc func, void* cookie) -{ - if (alignment == 0) { - if (bytesPerLine >= 16) alignment = 4; - else if (bytesPerLine >= 8) alignment = 2; - else alignment = 1; - } - if (func == NULL) func = defaultPrintFunc; - - size_t offset; - - unsigned char *pos = (unsigned char *)buf; - - if (pos == NULL) { - if (singleLineBytesCutoff < 0) func(cookie, "\n"); - func(cookie, "(NULL)"); - return; - } - - if (length == 0) { - if (singleLineBytesCutoff < 0) func(cookie, "\n"); - func(cookie, "(empty)"); - return; - } - - if ((int32_t)length < 0) { - if (singleLineBytesCutoff < 0) func(cookie, "\n"); - char buf[64]; - sprintf(buf, "(bad length: %d)", length); - func(cookie, buf); - return; - } - - char buffer[256]; - static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1); - - if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine; - - const bool oneLine = (int32_t)length <= singleLineBytesCutoff; - bool newLine = false; - if (cStyle) { - indent++; - func(cookie, "{\n"); - newLine = true; - } else if (!oneLine) { - func(cookie, "\n"); - newLine = true; - } - - for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) { - long remain = length; - - char* c = buffer; - if (!oneLine && !cStyle) { - sprintf(c, "0x%08x: ", (int)offset); - c += 12; - } - - size_t index; - size_t word; - - for (word = 0; word < bytesPerLine; ) { - -#ifdef HAVE_LITTLE_ENDIAN - const size_t startIndex = word+(alignment-(alignment?1:0)); - const ssize_t dir = -1; -#else - const size_t startIndex = word; - const ssize_t dir = 1; -#endif - - for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) { - - if (!cStyle) { - if (index == 0 && word > 0 && alignment > 0) { - *c++ = ' '; - } - - if (remain-- > 0) { - const unsigned char val = *(pos+startIndex+(index*dir)); - *c++ = makehexdigit(val>>4); - *c++ = makehexdigit(val); - } else if (!oneLine) { - *c++ = ' '; - *c++ = ' '; - } - } else { - if (remain > 0) { - if (index == 0 && word > 0) { - *c++ = ','; - *c++ = ' '; - } - if (index == 0) { - *c++ = '0'; - *c++ = 'x'; - } - const unsigned char val = *(pos+startIndex+(index*dir)); - *c++ = makehexdigit(val>>4); - *c++ = makehexdigit(val); - remain--; - } - } - } - - word += index; - } - - if (!cStyle) { - remain = length; - *c++ = ' '; - *c++ = '\''; - for (index = 0; index < bytesPerLine; index++) { - - if (remain-- > 0) { - const unsigned char val = pos[index]; - *c++ = (val >= ' ' && val < 127) ? val : '.'; - } else if (!oneLine) { - *c++ = ' '; - } - } - - *c++ = '\''; - if (length > bytesPerLine) *c++ = '\n'; - } else { - if (remain > 0) *c++ = ','; - *c++ = '\n'; - } - - if (newLine && indent) func(cookie, stringForIndent(indent)); - *c = 0; - func(cookie, buffer); - newLine = true; - - if (length <= bytesPerLine) break; - length -= bytesPerLine; - } - - if (cStyle) { - if (indent > 0) func(cookie, stringForIndent(indent-1)); - func(cookie, "};"); - } -} - -}; // namespace android - diff --git a/libs/utils/FileMap.cpp b/libs/utils/FileMap.cpp deleted file mode 100644 index e1ba9b2..0000000 --- a/libs/utils/FileMap.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Shared file mapping class. -// - -#define LOG_TAG "filemap" - -#include <utils/FileMap.h> -#include <utils/Log.h> - -#include <stdio.h> -#include <stdlib.h> - -#ifdef HAVE_POSIX_FILEMAP -#include <sys/mman.h> -#endif - -#include <string.h> -#include <memory.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - -/*static*/ long FileMap::mPageSize = -1; - - -/* - * Constructor. Create an empty object. - */ -FileMap::FileMap(void) - : mRefCount(1), mFileName(NULL), mBasePtr(NULL), mBaseLength(0), - mDataPtr(NULL), mDataLength(0) -{ -} - -/* - * Destructor. - */ -FileMap::~FileMap(void) -{ - assert(mRefCount == 0); - - //printf("+++ removing FileMap %p %u\n", mDataPtr, mDataLength); - - mRefCount = -100; // help catch double-free - if (mFileName != NULL) { - free(mFileName); - } -#ifdef HAVE_POSIX_FILEMAP - if (munmap(mBasePtr, mBaseLength) != 0) { - LOGD("munmap(%p, %d) failed\n", mBasePtr, (int) mBaseLength); - } -#endif -#ifdef HAVE_WIN32_FILEMAP - if ( UnmapViewOfFile(mBasePtr) == 0) { - LOGD("UnmapViewOfFile(%p) failed, error = %ld\n", mBasePtr, - GetLastError() ); - } - CloseHandle(mFileMapping); - CloseHandle(mFileHandle); -#endif -} - - -/* - * Create a new mapping on an open file. - * - * Closing the file descriptor does not unmap the pages, so we don't - * claim ownership of the fd. - * - * Returns "false" on failure. - */ -bool FileMap::create(const char* origFileName, int fd, off_t offset, size_t length, bool readOnly) -{ -#ifdef HAVE_WIN32_FILEMAP - int adjust; - off_t adjOffset; - size_t adjLength; - - if (mPageSize == -1) { - SYSTEM_INFO si; - - GetSystemInfo( &si ); - mPageSize = si.dwAllocationGranularity; - } - - DWORD protect = readOnly ? PAGE_READONLY : PAGE_READWRITE; - - mFileHandle = (HANDLE) _get_osfhandle(fd); - mFileMapping = CreateFileMapping( mFileHandle, NULL, protect, 0, 0, NULL); - if (mFileMapping == NULL) { - LOGE("CreateFileMapping(%p, %lx) failed with error %ld\n", - mFileHandle, protect, GetLastError() ); - return false; - } - - adjust = offset % mPageSize; - adjOffset = offset - adjust; - adjLength = length + adjust; - - mBasePtr = MapViewOfFile( mFileMapping, - readOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, - 0, - (DWORD)(adjOffset), - adjLength ); - if (mBasePtr == NULL) { - LOGE("MapViewOfFile(%ld, %ld) failed with error %ld\n", - adjOffset, adjLength, GetLastError() ); - CloseHandle(mFileMapping); - mFileMapping = INVALID_HANDLE_VALUE; - return false; - } -#endif -#ifdef HAVE_POSIX_FILEMAP - int prot, flags, adjust; - off_t adjOffset; - size_t adjLength; - - void* ptr; - - assert(mRefCount == 1); - assert(fd >= 0); - assert(offset >= 0); - assert(length > 0); - - /* init on first use */ - if (mPageSize == -1) { -#if NOT_USING_KLIBC - mPageSize = sysconf(_SC_PAGESIZE); - if (mPageSize == -1) { - LOGE("could not get _SC_PAGESIZE\n"); - return false; - } -#else - /* this holds for Linux, Darwin, Cygwin, and doesn't pain the ARM */ - mPageSize = 4096; -#endif - } - - adjust = offset % mPageSize; -try_again: - adjOffset = offset - adjust; - adjLength = length + adjust; - - flags = MAP_SHARED; - prot = PROT_READ; - if (!readOnly) - prot |= PROT_WRITE; - - ptr = mmap(NULL, adjLength, prot, flags, fd, adjOffset); - if (ptr == MAP_FAILED) { - // Cygwin does not seem to like file mapping files from an offset. - // So if we fail, try again with offset zero - if (adjOffset > 0) { - adjust = offset; - goto try_again; - } - - LOGE("mmap(%ld,%ld) failed: %s\n", - (long) adjOffset, (long) adjLength, strerror(errno)); - return false; - } - mBasePtr = ptr; -#endif /* HAVE_POSIX_FILEMAP */ - - mFileName = origFileName != NULL ? strdup(origFileName) : NULL; - mBaseLength = adjLength; - mDataOffset = offset; - mDataPtr = (char*) mBasePtr + adjust; - mDataLength = length; - - assert(mBasePtr != NULL); - - LOGV("MAP: base %p/%d data %p/%d\n", - mBasePtr, (int) mBaseLength, mDataPtr, (int) mDataLength); - - return true; -} - -/* - * Provide guidance to the system. - */ -int FileMap::advise(MapAdvice advice) -{ -#if HAVE_MADVISE - int cc, sysAdvice; - - switch (advice) { - case NORMAL: sysAdvice = MADV_NORMAL; break; - case RANDOM: sysAdvice = MADV_RANDOM; break; - case SEQUENTIAL: sysAdvice = MADV_SEQUENTIAL; break; - case WILLNEED: sysAdvice = MADV_WILLNEED; break; - case DONTNEED: sysAdvice = MADV_DONTNEED; break; - default: - assert(false); - return -1; - } - - cc = madvise(mBasePtr, mBaseLength, sysAdvice); - if (cc != 0) - LOGW("madvise(%d) failed: %s\n", sysAdvice, strerror(errno)); - return cc; -#else - return -1; -#endif // HAVE_MADVISE -} diff --git a/libs/utils/IDataConnection.cpp b/libs/utils/IDataConnection.cpp deleted file mode 100644 index c6d49aa..0000000 --- a/libs/utils/IDataConnection.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Parcel.h> - -#include <utils/IDataConnection.h> - -namespace android { - -// --------------------------------------------------------------------------- - -enum -{ - CONNECT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, - DISCONNECT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1 -}; - -class BpDataConnection : public BpInterface<IDataConnection> -{ -public: - BpDataConnection::BpDataConnection(const sp<IBinder>& impl) - : BpInterface<IDataConnection>(impl) - { - } - - virtual void connect() - { - Parcel data, reply; - data.writeInterfaceToken(IDataConnection::descriptor()); - remote()->transact(CONNECT_TRANSACTION, data, &reply); - } - - virtual void disconnect() - { - Parcel data, reply; - remote()->transact(DISCONNECT_TRANSACTION, data, &reply); - } -}; - -IMPLEMENT_META_INTERFACE(DataConnection, "android.utils.IDataConnection"); - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnDataConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) - { - case CONNECT_TRANSACTION: - { - CHECK_INTERFACE(IDataConnection, data, reply); - connect(); - return NO_ERROR; - } - - case DISCONNECT_TRANSACTION: - { - CHECK_INTERFACE(IDataConnection, data, reply); - disconnect(); - return NO_ERROR; - } - - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/utils/IInterface.cpp b/libs/utils/IInterface.cpp deleted file mode 100644 index 6ea8178..0000000 --- a/libs/utils/IInterface.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/IInterface.h> - -namespace android { - -// --------------------------------------------------------------------------- - -sp<IBinder> IInterface::asBinder() -{ - return this ? onAsBinder() : NULL; -} - -sp<const IBinder> IInterface::asBinder() const -{ - return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL; -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/utils/IMemory.cpp b/libs/utils/IMemory.cpp deleted file mode 100644 index 429bc2b..0000000 --- a/libs/utils/IMemory.cpp +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "IMemory" - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> - -#include <sys/types.h> -#include <sys/mman.h> - -#include <utils/IMemory.h> -#include <utils/KeyedVector.h> -#include <utils/threads.h> -#include <utils/Atomic.h> -#include <utils/Parcel.h> -#include <utils/CallStack.h> - -#define VERBOSE 0 - -namespace android { -// --------------------------------------------------------------------------- - -class HeapCache : public IBinder::DeathRecipient -{ -public: - HeapCache(); - virtual ~HeapCache(); - - virtual void binderDied(const wp<IBinder>& who); - - sp<IMemoryHeap> find_heap(const sp<IBinder>& binder); - void pin_heap(const sp<IBinder>& binder); - void free_heap(const sp<IBinder>& binder); - sp<IMemoryHeap> get_heap(const sp<IBinder>& binder); - void dump_heaps(); - -private: - // For IMemory.cpp - struct heap_info_t { - sp<IMemoryHeap> heap; - int32_t count; - }; - - void free_heap(const wp<IBinder>& binder); - - Mutex mHeapCacheLock; - KeyedVector< wp<IBinder>, heap_info_t > mHeapCache; -}; - -static sp<HeapCache> gHeapCache = new HeapCache(); - -/******************************************************************************/ - -enum { - HEAP_ID = IBinder::FIRST_CALL_TRANSACTION -}; - -class BpMemoryHeap : public BpInterface<IMemoryHeap> -{ -public: - BpMemoryHeap(const sp<IBinder>& impl); - virtual ~BpMemoryHeap(); - - virtual int getHeapID() const; - virtual void* getBase() const; - virtual size_t getSize() const; - virtual uint32_t getFlags() const; - -private: - friend class IMemory; - friend class HeapCache; - - // for debugging in this module - static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) { - return gHeapCache->find_heap(binder); - } - static inline void free_heap(const sp<IBinder>& binder) { - gHeapCache->free_heap(binder); - } - static inline sp<IMemoryHeap> get_heap(const sp<IBinder>& binder) { - return gHeapCache->get_heap(binder); - } - static inline void dump_heaps() { - gHeapCache->dump_heaps(); - } - void inline pin_heap() const { - gHeapCache->pin_heap(const_cast<BpMemoryHeap*>(this)->asBinder()); - } - - void assertMapped() const; - void assertReallyMapped() const; - void pinHeap() const; - - mutable volatile int32_t mHeapId; - mutable void* mBase; - mutable size_t mSize; - mutable uint32_t mFlags; - mutable bool mRealHeap; - mutable Mutex mLock; -}; - -// ---------------------------------------------------------------------------- - -enum { - GET_MEMORY = IBinder::FIRST_CALL_TRANSACTION -}; - -class BpMemory : public BpInterface<IMemory> -{ -public: - BpMemory(const sp<IBinder>& impl); - virtual ~BpMemory(); - virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const; - -private: - mutable sp<IMemoryHeap> mHeap; - mutable ssize_t mOffset; - mutable size_t mSize; -}; - -/******************************************************************************/ - -void* IMemory::fastPointer(const sp<IBinder>& binder, ssize_t offset) const -{ - sp<IMemoryHeap> realHeap = BpMemoryHeap::get_heap(binder); - void* const base = realHeap->base(); - if (base == MAP_FAILED) - return 0; - return static_cast<char*>(base) + offset; -} - -void* IMemory::pointer() const { - ssize_t offset; - sp<IMemoryHeap> heap = getMemory(&offset); - void* const base = heap!=0 ? heap->base() : MAP_FAILED; - if (base == MAP_FAILED) - return 0; - return static_cast<char*>(base) + offset; -} - -size_t IMemory::size() const { - size_t size; - getMemory(NULL, &size); - return size; -} - -ssize_t IMemory::offset() const { - ssize_t offset; - getMemory(&offset); - return offset; -} - -/******************************************************************************/ - -BpMemory::BpMemory(const sp<IBinder>& impl) - : BpInterface<IMemory>(impl), mOffset(0), mSize(0) -{ -} - -BpMemory::~BpMemory() -{ -} - -sp<IMemoryHeap> BpMemory::getMemory(ssize_t* offset, size_t* size) const -{ - if (mHeap == 0) { - Parcel data, reply; - data.writeInterfaceToken(IMemory::getInterfaceDescriptor()); - if (remote()->transact(GET_MEMORY, data, &reply) == NO_ERROR) { - sp<IBinder> heap = reply.readStrongBinder(); - ssize_t o = reply.readInt32(); - size_t s = reply.readInt32(); - if (heap != 0) { - mHeap = interface_cast<IMemoryHeap>(heap); - if (mHeap != 0) { - mOffset = o; - mSize = s; - } - } - } - } - if (offset) *offset = mOffset; - if (size) *size = mSize; - return mHeap; -} - -// --------------------------------------------------------------------------- - -IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory"); - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnMemory::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GET_MEMORY: { - CHECK_INTERFACE(IMemory, data, reply); - ssize_t offset; - size_t size; - reply->writeStrongBinder( getMemory(&offset, &size)->asBinder() ); - reply->writeInt32(offset); - reply->writeInt32(size); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - - -/******************************************************************************/ - -BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl) - : BpInterface<IMemoryHeap>(impl), - mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mRealHeap(false) -{ -} - -BpMemoryHeap::~BpMemoryHeap() { - if (mHeapId != -1) { - close(mHeapId); - if (mRealHeap) { - // by construction we're the last one - if (mBase != MAP_FAILED) { - sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder(); - - if (VERBOSE) { - LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d", - binder.get(), this, mSize, mHeapId); - CallStack stack; - stack.update(); - stack.dump("callstack"); - } - - munmap(mBase, mSize); - } - } else { - // remove from list only if it was mapped before - sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder(); - free_heap(binder); - } - } -} - -void BpMemoryHeap::assertMapped() const -{ - if (mHeapId == -1) { - sp<IBinder> binder(const_cast<BpMemoryHeap*>(this)->asBinder()); - sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get())); - heap->assertReallyMapped(); - if (heap->mBase != MAP_FAILED) { - Mutex::Autolock _l(mLock); - if (mHeapId == -1) { - mBase = heap->mBase; - mSize = heap->mSize; - android_atomic_write( dup( heap->mHeapId ), &mHeapId ); - } - } else { - // something went wrong - free_heap(binder); - } - } -} - -void BpMemoryHeap::assertReallyMapped() const -{ - if (mHeapId == -1) { - - // remote call without mLock held, worse case scenario, we end up - // calling transact() from multiple threads, but that's not a problem, - // only mmap below must be in the critical section. - - Parcel data, reply; - data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor()); - status_t err = remote()->transact(HEAP_ID, data, &reply); - int parcel_fd = reply.readFileDescriptor(); - ssize_t size = reply.readInt32(); - uint32_t flags = reply.readInt32(); - - LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%d, err=%d (%s)", - asBinder().get(), parcel_fd, size, err, strerror(-err)); - - int fd = dup( parcel_fd ); - LOGE_IF(fd==-1, "cannot dup fd=%d, size=%d, err=%d (%s)", - parcel_fd, size, err, strerror(errno)); - - int access = PROT_READ; - if (!(flags & READ_ONLY)) { - access |= PROT_WRITE; - } - - Mutex::Autolock _l(mLock); - if (mHeapId == -1) { - mRealHeap = true; - mBase = mmap(0, size, access, MAP_SHARED, fd, 0); - if (mBase == MAP_FAILED) { - LOGE("cannot map BpMemoryHeap (binder=%p), size=%d, fd=%d (%s)", - asBinder().get(), size, fd, strerror(errno)); - close(fd); - } else { - if (flags & MAP_ONCE) { - //LOGD("pinning heap (binder=%p, size=%d, fd=%d", - // asBinder().get(), size, fd); - pin_heap(); - } - mSize = size; - mFlags = flags; - android_atomic_write(fd, &mHeapId); - } - } - } -} - -int BpMemoryHeap::getHeapID() const { - assertMapped(); - return mHeapId; -} - -void* BpMemoryHeap::getBase() const { - assertMapped(); - return mBase; -} - -size_t BpMemoryHeap::getSize() const { - assertMapped(); - return mSize; -} - -uint32_t BpMemoryHeap::getFlags() const { - assertMapped(); - return mFlags; -} - -// --------------------------------------------------------------------------- - -IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap"); - -status_t BnMemoryHeap::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case HEAP_ID: { - CHECK_INTERFACE(IMemoryHeap, data, reply); - reply->writeFileDescriptor(getHeapID()); - reply->writeInt32(getSize()); - reply->writeInt32(getFlags()); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -/*****************************************************************************/ - -HeapCache::HeapCache() - : DeathRecipient() -{ -} - -HeapCache::~HeapCache() -{ -} - -void HeapCache::binderDied(const wp<IBinder>& binder) -{ - //LOGD("binderDied binder=%p", binder.unsafe_get()); - free_heap(binder); -} - -sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder) -{ - Mutex::Autolock _l(mHeapCacheLock); - ssize_t i = mHeapCache.indexOfKey(binder); - if (i>=0) { - heap_info_t& info = mHeapCache.editValueAt(i); - LOGD_IF(VERBOSE, - "found binder=%p, heap=%p, size=%d, fd=%d, count=%d", - binder.get(), info.heap.get(), - static_cast<BpMemoryHeap*>(info.heap.get())->mSize, - static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId, - info.count); - android_atomic_inc(&info.count); - return info.heap; - } else { - heap_info_t info; - info.heap = interface_cast<IMemoryHeap>(binder); - info.count = 1; - //LOGD("adding binder=%p, heap=%p, count=%d", - // binder.get(), info.heap.get(), info.count); - mHeapCache.add(binder, info); - return info.heap; - } -} - -void HeapCache::pin_heap(const sp<IBinder>& binder) -{ - Mutex::Autolock _l(mHeapCacheLock); - ssize_t i = mHeapCache.indexOfKey(binder); - if (i>=0) { - heap_info_t& info(mHeapCache.editValueAt(i)); - android_atomic_inc(&info.count); - binder->linkToDeath(this); - } else { - LOGE("pin_heap binder=%p not found!!!", binder.get()); - } -} - -void HeapCache::free_heap(const sp<IBinder>& binder) { - free_heap( wp<IBinder>(binder) ); -} - -void HeapCache::free_heap(const wp<IBinder>& binder) -{ - sp<IMemoryHeap> rel; - { - Mutex::Autolock _l(mHeapCacheLock); - ssize_t i = mHeapCache.indexOfKey(binder); - if (i>=0) { - heap_info_t& info(mHeapCache.editValueAt(i)); - int32_t c = android_atomic_dec(&info.count); - if (c == 1) { - LOGD_IF(VERBOSE, - "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d", - binder.unsafe_get(), info.heap.get(), - static_cast<BpMemoryHeap*>(info.heap.get())->mSize, - static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId, - info.count); - rel = mHeapCache.valueAt(i).heap; - mHeapCache.removeItemsAt(i); - } - } else { - LOGE("free_heap binder=%p not found!!!", binder.unsafe_get()); - } - } -} - -sp<IMemoryHeap> HeapCache::get_heap(const sp<IBinder>& binder) -{ - sp<IMemoryHeap> realHeap; - Mutex::Autolock _l(mHeapCacheLock); - ssize_t i = mHeapCache.indexOfKey(binder); - if (i>=0) realHeap = mHeapCache.valueAt(i).heap; - else realHeap = interface_cast<IMemoryHeap>(binder); - return realHeap; -} - -void HeapCache::dump_heaps() -{ - Mutex::Autolock _l(mHeapCacheLock); - int c = mHeapCache.size(); - for (int i=0 ; i<c ; i++) { - const heap_info_t& info = mHeapCache.valueAt(i); - BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get())); - LOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%d)", - mHeapCache.keyAt(i).unsafe_get(), - info.heap.get(), info.count, - h->mHeapId, h->mBase, h->mSize); - } -} - - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/utils/IPCThreadState.cpp b/libs/utils/IPCThreadState.cpp deleted file mode 100644 index 04ae142..0000000 --- a/libs/utils/IPCThreadState.cpp +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/IPCThreadState.h> - -#include <utils/Binder.h> -#include <utils/BpBinder.h> -#include <utils/Debug.h> -#include <utils/Log.h> -#include <utils/TextOutput.h> -#include <utils/threads.h> - -#include <private/utils/binder_module.h> -#include <private/utils/Static.h> - -#include <sys/ioctl.h> -#include <signal.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> - -#ifdef HAVE_PTHREADS -#include <pthread.h> -#include <sched.h> -#include <sys/resource.h> -#endif -#ifdef HAVE_WIN32_THREADS -#include <windows.h> -#endif - - -#if LOG_NDEBUG - -#define IF_LOG_TRANSACTIONS() if (false) -#define IF_LOG_COMMANDS() if (false) -#define LOG_REMOTEREFS(...) -#define IF_LOG_REMOTEREFS() if (false) -#define LOG_THREADPOOL(...) -#define LOG_ONEWAY(...) - -#else - -#define IF_LOG_TRANSACTIONS() IF_LOG(LOG_VERBOSE, "transact") -#define IF_LOG_COMMANDS() IF_LOG(LOG_VERBOSE, "ipc") -#define LOG_REMOTEREFS(...) LOG(LOG_DEBUG, "remoterefs", __VA_ARGS__) -#define IF_LOG_REMOTEREFS() IF_LOG(LOG_DEBUG, "remoterefs") -#define LOG_THREADPOOL(...) LOG(LOG_DEBUG, "threadpool", __VA_ARGS__) -#define LOG_ONEWAY(...) LOG(LOG_DEBUG, "ipc", __VA_ARGS__) - -#endif - -// --------------------------------------------------------------------------- - -namespace android { - -static const char* getReturnString(size_t idx); -static const char* getCommandString(size_t idx); -static const void* printReturnCommand(TextOutput& out, const void* _cmd); -static const void* printCommand(TextOutput& out, const void* _cmd); - -// This will result in a missing symbol failure if the IF_LOG_COMMANDS() -// conditionals don't get stripped... but that is probably what we want. -#if !LOG_NDEBUG -static const char *kReturnStrings[] = { -#if 1 /* TODO: error update strings */ - "unknown", -#else - "BR_OK", - "BR_TIMEOUT", - "BR_WAKEUP", - "BR_TRANSACTION", - "BR_REPLY", - "BR_ACQUIRE_RESULT", - "BR_DEAD_REPLY", - "BR_TRANSACTION_COMPLETE", - "BR_INCREFS", - "BR_ACQUIRE", - "BR_RELEASE", - "BR_DECREFS", - "BR_ATTEMPT_ACQUIRE", - "BR_EVENT_OCCURRED", - "BR_NOOP", - "BR_SPAWN_LOOPER", - "BR_FINISHED", - "BR_DEAD_BINDER", - "BR_CLEAR_DEATH_NOTIFICATION_DONE" -#endif -}; - -static const char *kCommandStrings[] = { -#if 1 /* TODO: error update strings */ - "unknown", -#else - "BC_NOOP", - "BC_TRANSACTION", - "BC_REPLY", - "BC_ACQUIRE_RESULT", - "BC_FREE_BUFFER", - "BC_TRANSACTION_COMPLETE", - "BC_INCREFS", - "BC_ACQUIRE", - "BC_RELEASE", - "BC_DECREFS", - "BC_INCREFS_DONE", - "BC_ACQUIRE_DONE", - "BC_ATTEMPT_ACQUIRE", - "BC_RETRIEVE_ROOT_OBJECT", - "BC_SET_THREAD_ENTRY", - "BC_REGISTER_LOOPER", - "BC_ENTER_LOOPER", - "BC_EXIT_LOOPER", - "BC_SYNC", - "BC_STOP_PROCESS", - "BC_STOP_SELF", - "BC_REQUEST_DEATH_NOTIFICATION", - "BC_CLEAR_DEATH_NOTIFICATION", - "BC_DEAD_BINDER_DONE" -#endif -}; - -static const char* getReturnString(size_t idx) -{ - if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0])) - return kReturnStrings[idx]; - else - return "unknown"; -} - -static const char* getCommandString(size_t idx) -{ - if (idx < sizeof(kCommandStrings) / sizeof(kCommandStrings[0])) - return kCommandStrings[idx]; - else - return "unknown"; -} - -static const void* printBinderTransactionData(TextOutput& out, const void* data) -{ - const binder_transaction_data* btd = - (const binder_transaction_data*)data; - out << "target=" << btd->target.ptr << " (cookie " << btd->cookie << ")" << endl - << "code=" << TypeCode(btd->code) << ", flags=" << (void*)btd->flags << endl - << "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size - << " bytes)" << endl - << "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size - << " bytes)" << endl; - return btd+1; -} - -static const void* printReturnCommand(TextOutput& out, const void* _cmd) -{ - static const int32_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]); - - const int32_t* cmd = (const int32_t*)_cmd; - int32_t code = *cmd++; - if (code == BR_ERROR) { - out << "BR_ERROR: " << (void*)(*cmd++) << endl; - return cmd; - } else if (code < 0 || code >= N) { - out << "Unknown reply: " << code << endl; - return cmd; - } - - out << kReturnStrings[code]; - switch (code) { - case BR_TRANSACTION: - case BR_REPLY: { - out << ": " << indent; - cmd = (const int32_t *)printBinderTransactionData(out, cmd); - out << dedent; - } break; - - case BR_ACQUIRE_RESULT: { - const int32_t res = *cmd++; - out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)"); - } break; - - case BR_INCREFS: - case BR_ACQUIRE: - case BR_RELEASE: - case BR_DECREFS: { - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c << ")"; - } break; - - case BR_ATTEMPT_ACQUIRE: { - const int32_t p = *cmd++; - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c - << "), pri=" << p; - } break; - - case BR_DEAD_BINDER: - case BR_CLEAR_DEATH_NOTIFICATION_DONE: { - const int32_t c = *cmd++; - out << ": death cookie " << (void*)c; - } break; - } - - out << endl; - return cmd; -} - -static const void* printCommand(TextOutput& out, const void* _cmd) -{ - static const int32_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]); - - const int32_t* cmd = (const int32_t*)_cmd; - int32_t code = *cmd++; - if (code < 0 || code >= N) { - out << "Unknown command: " << code << endl; - return cmd; - } - - out << kCommandStrings[code]; - switch (code) { - case BC_TRANSACTION: - case BC_REPLY: { - out << ": " << indent; - cmd = (const int32_t *)printBinderTransactionData(out, cmd); - out << dedent; - } break; - - case BC_ACQUIRE_RESULT: { - const int32_t res = *cmd++; - out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)"); - } break; - - case BC_FREE_BUFFER: { - const int32_t buf = *cmd++; - out << ": buffer=" << (void*)buf; - } break; - - case BC_INCREFS: - case BC_ACQUIRE: - case BC_RELEASE: - case BC_DECREFS: { - const int32_t d = *cmd++; - out << ": descriptor=" << (void*)d; - } break; - - case BC_INCREFS_DONE: - case BC_ACQUIRE_DONE: { - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c << ")"; - } break; - - case BC_ATTEMPT_ACQUIRE: { - const int32_t p = *cmd++; - const int32_t d = *cmd++; - out << ": decriptor=" << (void*)d << ", pri=" << p; - } break; - - case BC_REQUEST_DEATH_NOTIFICATION: - case BC_CLEAR_DEATH_NOTIFICATION: { - const int32_t h = *cmd++; - const int32_t c = *cmd++; - out << ": handle=" << h << " (death cookie " << (void*)c << ")"; - } break; - - case BC_DEAD_BINDER_DONE: { - const int32_t c = *cmd++; - out << ": death cookie " << (void*)c; - } break; - } - - out << endl; - return cmd; -} -#endif - -static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; -static bool gHaveTLS = false; -static pthread_key_t gTLS = 0; -static bool gShutdown = false; - -IPCThreadState* IPCThreadState::self() -{ - if (gHaveTLS) { -restart: - const pthread_key_t k = gTLS; - IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); - if (st) return st; - return new IPCThreadState; - } - - if (gShutdown) return NULL; - - pthread_mutex_lock(&gTLSMutex); - if (!gHaveTLS) { - if (pthread_key_create(&gTLS, threadDestructor) != 0) { - pthread_mutex_unlock(&gTLSMutex); - return NULL; - } - gHaveTLS = true; - } - pthread_mutex_unlock(&gTLSMutex); - goto restart; -} - -void IPCThreadState::shutdown() -{ - gShutdown = true; - - if (gHaveTLS) { - // XXX Need to wait for all thread pool threads to exit! - IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS); - if (st) { - delete st; - pthread_setspecific(gTLS, NULL); - } - gHaveTLS = false; - } -} - -sp<ProcessState> IPCThreadState::process() -{ - return mProcess; -} - -status_t IPCThreadState::clearLastError() -{ - const status_t err = mLastError; - mLastError = NO_ERROR; - return err; -} - -int IPCThreadState::getCallingPid() -{ - return mCallingPid; -} - -int IPCThreadState::getCallingUid() -{ - return mCallingUid; -} - -int64_t IPCThreadState::clearCallingIdentity() -{ - int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid; - clearCaller(); - return token; -} - -void IPCThreadState::restoreCallingIdentity(int64_t token) -{ - mCallingUid = (int)(token>>32); - mCallingPid = (int)token; -} - -void IPCThreadState::clearCaller() -{ - if (mProcess->supportsProcesses()) { - mCallingPid = getpid(); - mCallingUid = getuid(); - } else { - mCallingPid = -1; - mCallingUid = -1; - } -} - -void IPCThreadState::flushCommands() -{ - if (mProcess->mDriverFD <= 0) - return; - talkWithDriver(false); -} - -void IPCThreadState::joinThreadPool(bool isMain) -{ - LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); - - mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); - - status_t result; - do { - int32_t cmd; - - // When we've cleared the incoming command queue, process any pending derefs - if (mIn.dataPosition() >= mIn.dataSize()) { - size_t numPending = mPendingWeakDerefs.size(); - if (numPending > 0) { - for (size_t i = 0; i < numPending; i++) { - RefBase::weakref_type* refs = mPendingWeakDerefs[i]; - refs->decWeak(mProcess.get()); - } - mPendingWeakDerefs.clear(); - } - - numPending = mPendingStrongDerefs.size(); - if (numPending > 0) { - for (size_t i = 0; i < numPending; i++) { - BBinder* obj = mPendingStrongDerefs[i]; - obj->decStrong(mProcess.get()); - } - mPendingStrongDerefs.clear(); - } - } - - // now get the next command to be processed, waiting if necessary - result = talkWithDriver(); - if (result >= NO_ERROR) { - size_t IN = mIn.dataAvail(); - if (IN < sizeof(int32_t)) continue; - cmd = mIn.readInt32(); - IF_LOG_COMMANDS() { - alog << "Processing top-level Command: " - << getReturnString(cmd) << endl; - } - result = executeCommand(cmd); - } - - // Let this thread exit the thread pool if it is no longer - // needed and it is not the main process thread. - if(result == TIMED_OUT && !isMain) { - break; - } - } while (result != -ECONNREFUSED && result != -EBADF); - - LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n", - (void*)pthread_self(), getpid(), (void*)result); - - mOut.writeInt32(BC_EXIT_LOOPER); - talkWithDriver(false); -} - -void IPCThreadState::stopProcess(bool immediate) -{ - //LOGI("**** STOPPING PROCESS"); - flushCommands(); - int fd = mProcess->mDriverFD; - mProcess->mDriverFD = -1; - close(fd); - //kill(getpid(), SIGKILL); -} - -status_t IPCThreadState::transact(int32_t handle, - uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags) -{ - status_t err = data.errorCheck(); - - flags |= TF_ACCEPT_FDS; - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " - << handle << " / code " << TypeCode(code) << ": " - << indent << data << dedent << endl; - } - - if (err == NO_ERROR) { - LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), - (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); - err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); - } - - if (err != NO_ERROR) { - if (reply) reply->setError(err); - return (mLastError = err); - } - - if ((flags & TF_ONE_WAY) == 0) { - if (reply) { - err = waitForResponse(reply); - } else { - Parcel fakeReply; - err = waitForResponse(&fakeReply); - } - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand " - << handle << ": "; - if (reply) alog << indent << *reply << dedent << endl; - else alog << "(none requested)" << endl; - } - } else { - err = waitForResponse(NULL, NULL); - } - - return err; -} - -void IPCThreadState::incStrongHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::incStrongHandle(%d)\n", handle); - mOut.writeInt32(BC_ACQUIRE); - mOut.writeInt32(handle); -} - -void IPCThreadState::decStrongHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::decStrongHandle(%d)\n", handle); - mOut.writeInt32(BC_RELEASE); - mOut.writeInt32(handle); -} - -void IPCThreadState::incWeakHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle); - mOut.writeInt32(BC_INCREFS); - mOut.writeInt32(handle); -} - -void IPCThreadState::decWeakHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::decWeakHandle(%d)\n", handle); - mOut.writeInt32(BC_DECREFS); - mOut.writeInt32(handle); -} - -status_t IPCThreadState::attemptIncStrongHandle(int32_t handle) -{ - mOut.writeInt32(BC_ATTEMPT_ACQUIRE); - mOut.writeInt32(0); // xxx was thread priority - mOut.writeInt32(handle); - status_t result = UNKNOWN_ERROR; - - waitForResponse(NULL, &result); - -#if LOG_REFCOUNTS - printf("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n", - handle, result == NO_ERROR ? "SUCCESS" : "FAILURE"); -#endif - - return result; -} - -void IPCThreadState::expungeHandle(int32_t handle, IBinder* binder) -{ -#if LOG_REFCOUNTS - printf("IPCThreadState::expungeHandle(%ld)\n", handle); -#endif - self()->mProcess->expungeHandle(handle, binder); -} - -status_t IPCThreadState::requestDeathNotification(int32_t handle, BpBinder* proxy) -{ - mOut.writeInt32(BC_REQUEST_DEATH_NOTIFICATION); - mOut.writeInt32((int32_t)handle); - mOut.writeInt32((int32_t)proxy); - return NO_ERROR; -} - -status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) -{ - mOut.writeInt32(BC_CLEAR_DEATH_NOTIFICATION); - mOut.writeInt32((int32_t)handle); - mOut.writeInt32((int32_t)proxy); - return NO_ERROR; -} - -IPCThreadState::IPCThreadState() - : mProcess(ProcessState::self()) -{ - pthread_setspecific(gTLS, this); - clearCaller(); - mIn.setDataCapacity(256); - mOut.setDataCapacity(256); -} - -IPCThreadState::~IPCThreadState() -{ -} - -status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags) -{ - status_t err; - status_t statusBuffer; - err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer); - if (err < NO_ERROR) return err; - - return waitForResponse(NULL, NULL); -} - -status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) -{ - int32_t cmd; - int32_t err; - - while (1) { - if ((err=talkWithDriver()) < NO_ERROR) break; - err = mIn.errorCheck(); - if (err < NO_ERROR) break; - if (mIn.dataAvail() == 0) continue; - - cmd = mIn.readInt32(); - - IF_LOG_COMMANDS() { - alog << "Processing waitForResponse Command: " - << getReturnString(cmd) << endl; - } - - switch (cmd) { - case BR_TRANSACTION_COMPLETE: - if (!reply && !acquireResult) goto finish; - break; - - case BR_DEAD_REPLY: - err = DEAD_OBJECT; - goto finish; - - case BR_FAILED_REPLY: - err = FAILED_TRANSACTION; - goto finish; - - case BR_ACQUIRE_RESULT: - { - LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); - const int32_t result = mIn.readInt32(); - if (!acquireResult) continue; - *acquireResult = result ? NO_ERROR : INVALID_OPERATION; - } - goto finish; - - case BR_REPLY: - { - binder_transaction_data tr; - err = mIn.read(&tr, sizeof(tr)); - LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY"); - if (err != NO_ERROR) goto finish; - - if (reply) { - if ((tr.flags & TF_STATUS_CODE) == 0) { - reply->ipcSetDataReference( - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), - freeBuffer, this); - } else { - err = *static_cast<const status_t*>(tr.data.ptr.buffer); - freeBuffer(NULL, - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), this); - } - } else { - freeBuffer(NULL, - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), this); - continue; - } - } - goto finish; - - default: - err = executeCommand(cmd); - if (err != NO_ERROR) goto finish; - break; - } - } - -finish: - if (err != NO_ERROR) { - if (acquireResult) *acquireResult = err; - if (reply) reply->setError(err); - mLastError = err; - } - - return err; -} - -status_t IPCThreadState::talkWithDriver(bool doReceive) -{ - LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened"); - - binder_write_read bwr; - - // Is the read buffer empty? - const bool needRead = mIn.dataPosition() >= mIn.dataSize(); - - // We don't want to write anything if we are still reading - // from data left in the input buffer and the caller - // has requested to read the next data. - const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; - - bwr.write_size = outAvail; - bwr.write_buffer = (long unsigned int)mOut.data(); - - // This is what we'll read. - if (doReceive && needRead) { - bwr.read_size = mIn.dataCapacity(); - bwr.read_buffer = (long unsigned int)mIn.data(); - } else { - bwr.read_size = 0; - } - - IF_LOG_COMMANDS() { - TextOutput::Bundle _b(alog); - if (outAvail != 0) { - alog << "Sending commands to driver: " << indent; - const void* cmds = (const void*)bwr.write_buffer; - const void* end = ((const uint8_t*)cmds)+bwr.write_size; - alog << HexDump(cmds, bwr.write_size) << endl; - while (cmds < end) cmds = printCommand(alog, cmds); - alog << dedent; - } - alog << "Size of receive buffer: " << bwr.read_size - << ", needRead: " << needRead << ", doReceive: " << doReceive << endl; - } - - // Return immediately if there is nothing to do. - if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR; - - bwr.write_consumed = 0; - bwr.read_consumed = 0; - status_t err; - do { - IF_LOG_COMMANDS() { - alog << "About to read/write, write size = " << mOut.dataSize() << endl; - } -#if defined(HAVE_ANDROID_OS) - if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) - err = NO_ERROR; - else - err = -errno; -#else - err = INVALID_OPERATION; -#endif - IF_LOG_COMMANDS() { - alog << "Finished read/write, write size = " << mOut.dataSize() << endl; - } - } while (err == -EINTR); - - IF_LOG_COMMANDS() { - alog << "Our err: " << (void*)err << ", write consumed: " - << bwr.write_consumed << " (of " << mOut.dataSize() - << "), read consumed: " << bwr.read_consumed << endl; - } - - if (err >= NO_ERROR) { - if (bwr.write_consumed > 0) { - if (bwr.write_consumed < (ssize_t)mOut.dataSize()) - mOut.remove(0, bwr.write_consumed); - else - mOut.setDataSize(0); - } - if (bwr.read_consumed > 0) { - mIn.setDataSize(bwr.read_consumed); - mIn.setDataPosition(0); - } - IF_LOG_COMMANDS() { - TextOutput::Bundle _b(alog); - alog << "Remaining data size: " << mOut.dataSize() << endl; - alog << "Received commands from driver: " << indent; - const void* cmds = mIn.data(); - const void* end = mIn.data() + mIn.dataSize(); - alog << HexDump(cmds, mIn.dataSize()) << endl; - while (cmds < end) cmds = printReturnCommand(alog, cmds); - alog << dedent; - } - return NO_ERROR; - } - - return err; -} - -status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, - int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) -{ - binder_transaction_data tr; - - tr.target.handle = handle; - tr.code = code; - tr.flags = binderFlags; - - const status_t err = data.errorCheck(); - if (err == NO_ERROR) { - tr.data_size = data.ipcDataSize(); - tr.data.ptr.buffer = data.ipcData(); - tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t); - tr.data.ptr.offsets = data.ipcObjects(); - } else if (statusBuffer) { - tr.flags |= TF_STATUS_CODE; - *statusBuffer = err; - tr.data_size = sizeof(status_t); - tr.data.ptr.buffer = statusBuffer; - tr.offsets_size = 0; - tr.data.ptr.offsets = NULL; - } else { - return (mLastError = err); - } - - mOut.writeInt32(cmd); - mOut.write(&tr, sizeof(tr)); - - return NO_ERROR; -} - -sp<BBinder> the_context_object; - -void setTheContextObject(sp<BBinder> obj) -{ - the_context_object = obj; -} - -status_t IPCThreadState::executeCommand(int32_t cmd) -{ - BBinder* obj; - RefBase::weakref_type* refs; - status_t result = NO_ERROR; - - switch (cmd) { - case BR_ERROR: - result = mIn.readInt32(); - break; - - case BR_OK: - break; - - case BR_ACQUIRE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - LOG_ASSERT(refs->refBase() == obj, - "BR_ACQUIRE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - obj->incStrong(mProcess.get()); - IF_LOG_REMOTEREFS() { - LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj); - obj->printRefs(); - } - mOut.writeInt32(BC_ACQUIRE_DONE); - mOut.writeInt32((int32_t)refs); - mOut.writeInt32((int32_t)obj); - break; - - case BR_RELEASE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - LOG_ASSERT(refs->refBase() == obj, - "BR_RELEASE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - IF_LOG_REMOTEREFS() { - LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj); - obj->printRefs(); - } - mPendingStrongDerefs.push(obj); - break; - - case BR_INCREFS: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - refs->incWeak(mProcess.get()); - mOut.writeInt32(BC_INCREFS_DONE); - mOut.writeInt32((int32_t)refs); - mOut.writeInt32((int32_t)obj); - break; - - case BR_DECREFS: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - // NOTE: This assertion is not valid, because the object may no - // longer exist (thus the (BBinder*)cast above resulting in a different - // memory address). - //LOG_ASSERT(refs->refBase() == obj, - // "BR_DECREFS: object %p does not match cookie %p (expected %p)", - // refs, obj, refs->refBase()); - mPendingWeakDerefs.push(refs); - break; - - case BR_ATTEMPT_ACQUIRE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - - { - const bool success = refs->attemptIncStrong(mProcess.get()); - LOG_ASSERT(success && refs->refBase() == obj, - "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - - mOut.writeInt32(BC_ACQUIRE_RESULT); - mOut.writeInt32((int32_t)success); - } - break; - - case BR_TRANSACTION: - { - binder_transaction_data tr; - result = mIn.read(&tr, sizeof(tr)); - LOG_ASSERT(result == NO_ERROR, - "Not enough command data for brTRANSACTION"); - if (result != NO_ERROR) break; - - Parcel buffer; - buffer.ipcSetDataReference( - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), freeBuffer, this); - - const pid_t origPid = mCallingPid; - const uid_t origUid = mCallingUid; - - mCallingPid = tr.sender_pid; - mCallingUid = tr.sender_euid; - - //LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); - - Parcel reply; - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BR_TRANSACTION thr " << (void*)pthread_self() - << " / obj " << tr.target.ptr << " / code " - << TypeCode(tr.code) << ": " << indent << buffer - << dedent << endl - << "Data addr = " - << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer) - << ", offsets addr=" - << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl; - } - if (tr.target.ptr) { - sp<BBinder> b((BBinder*)tr.cookie); - const status_t error = b->transact(tr.code, buffer, &reply, 0); - if (error < NO_ERROR) reply.setError(error); - - } else { - const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0); - if (error < NO_ERROR) reply.setError(error); - } - - //LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n", - // mCallingPid, origPid, origUid); - - if ((tr.flags & TF_ONE_WAY) == 0) { - LOG_ONEWAY("Sending reply to %d!", mCallingPid); - sendReply(reply, 0); - } else { - LOG_ONEWAY("NOT sending reply to %d!", mCallingPid); - } - - mCallingPid = origPid; - mCallingUid = origUid; - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " - << tr.target.ptr << ": " << indent << reply << dedent << endl; - } - - } - break; - - case BR_DEAD_BINDER: - { - BpBinder *proxy = (BpBinder*)mIn.readInt32(); - proxy->sendObituary(); - mOut.writeInt32(BC_DEAD_BINDER_DONE); - mOut.writeInt32((int32_t)proxy); - } break; - - case BR_CLEAR_DEATH_NOTIFICATION_DONE: - { - BpBinder *proxy = (BpBinder*)mIn.readInt32(); - proxy->getWeakRefs()->decWeak(proxy); - } break; - - case BR_FINISHED: - result = TIMED_OUT; - break; - - case BR_NOOP: - break; - - case BR_SPAWN_LOOPER: - mProcess->spawnPooledThread(false); - break; - - default: - printf("*** BAD COMMAND %d received from Binder driver\n", cmd); - result = UNKNOWN_ERROR; - break; - } - - if (result != NO_ERROR) { - mLastError = result; - } - - return result; -} - -void IPCThreadState::threadDestructor(void *st) -{ - IPCThreadState* const self = static_cast<IPCThreadState*>(st); - if (self) { - self->flushCommands(); -#if defined(HAVE_ANDROID_OS) - ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0); -#endif - delete self; - } -} - - -void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data, size_t dataSize, - const size_t* objects, size_t objectsSize, - void* cookie) -{ - //LOGI("Freeing parcel %p", &parcel); - IF_LOG_COMMANDS() { - alog << "Writing BC_FREE_BUFFER for " << data << endl; - } - LOG_ASSERT(data != NULL, "Called with NULL data"); - if (parcel != NULL) parcel->closeFileDescriptors(); - IPCThreadState* state = self(); - state->mOut.writeInt32(BC_FREE_BUFFER); - state->mOut.writeInt32((int32_t)data); -} - -}; // namespace android diff --git a/libs/utils/IPermissionController.cpp b/libs/utils/IPermissionController.cpp deleted file mode 100644 index f01d38f..0000000 --- a/libs/utils/IPermissionController.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "PermissionController" - -#include <utils/IPermissionController.h> - -#include <utils/Debug.h> -#include <utils/Log.h> -#include <utils/Parcel.h> -#include <utils/String8.h> - -#include <private/utils/Static.h> - -namespace android { - -// ---------------------------------------------------------------------- - -class BpPermissionController : public BpInterface<IPermissionController> -{ -public: - BpPermissionController(const sp<IBinder>& impl) - : BpInterface<IPermissionController>(impl) - { - } - - virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid) - { - Parcel data, reply; - data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor()); - data.writeString16(permission); - data.writeInt32(pid); - data.writeInt32(uid); - remote()->transact(CHECK_PERMISSION_TRANSACTION, data, &reply); - // fail on exception - if (reply.readInt32() != 0) return 0; - return reply.readInt32() != 0; - } -}; - -IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnPermissionController::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - //printf("PermissionController received: "); data.print(); - switch(code) { - case CHECK_PERMISSION_TRANSACTION: { - CHECK_INTERFACE(IPermissionController, data, reply); - String16 permission = data.readString16(); - int32_t pid = data.readInt32(); - int32_t uid = data.readInt32(); - bool res = checkPermission(permission, pid, uid); - // write exception - reply->writeInt32(0); - reply->writeInt32(res ? 1 : 0); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android - diff --git a/libs/utils/IServiceManager.cpp b/libs/utils/IServiceManager.cpp deleted file mode 100644 index 9beeadd..0000000 --- a/libs/utils/IServiceManager.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "ServiceManager" - -#include <utils/IServiceManager.h> - -#include <utils/Debug.h> -#include <utils/IPCThreadState.h> -#include <utils/Log.h> -#include <utils/Parcel.h> -#include <utils/String8.h> -#include <utils/SystemClock.h> - -#include <private/utils/Static.h> - -#include <unistd.h> - -namespace android { - -sp<IServiceManager> defaultServiceManager() -{ - if (gDefaultServiceManager != NULL) return gDefaultServiceManager; - - { - AutoMutex _l(gDefaultServiceManagerLock); - if (gDefaultServiceManager == NULL) { - gDefaultServiceManager = interface_cast<IServiceManager>( - ProcessState::self()->getContextObject(NULL)); - } - } - - return gDefaultServiceManager; -} - -bool checkCallingPermission(const String16& permission) -{ - return checkCallingPermission(permission, NULL, NULL); -} - -static String16 _permission("permission"); - -bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid) -{ - IPCThreadState* ipcState = IPCThreadState::self(); - int32_t pid = ipcState->getCallingPid(); - int32_t uid = ipcState->getCallingUid(); - if (outPid) *outPid = pid; - if (outUid) *outUid= uid; - - sp<IPermissionController> pc; - gDefaultServiceManagerLock.lock(); - pc = gPermissionController; - gDefaultServiceManagerLock.unlock(); - - int64_t startTime = 0; - - while (true) { - if (pc != NULL) { - bool res = pc->checkPermission(permission, pid, uid); - if (res) { - if (startTime != 0) { - LOGI("Check passed after %d seconds for %s from uid=%d pid=%d", - (int)((uptimeMillis()-startTime)/1000), - String8(permission).string(), uid, pid); - } - return res; - } - - // Is this a permission failure, or did the controller go away? - if (pc->asBinder()->isBinderAlive()) { - LOGW("Permission failure: %s from uid=%d pid=%d", - String8(permission).string(), uid, pid); - return false; - } - - // Object is dead! - gDefaultServiceManagerLock.lock(); - if (gPermissionController == pc) { - gPermissionController = NULL; - } - gDefaultServiceManagerLock.unlock(); - } - - // Need to retrieve the permission controller. - sp<IBinder> binder = defaultServiceManager()->checkService(_permission); - if (binder == NULL) { - // Wait for the permission controller to come back... - if (startTime == 0) { - startTime = uptimeMillis(); - LOGI("Waiting to check permission %s from uid=%d pid=%d", - String8(permission).string(), uid, pid); - } - sleep(1); - } else { - pc = interface_cast<IPermissionController>(binder); - // Install the new permission controller, and try again. - gDefaultServiceManagerLock.lock(); - gPermissionController = pc; - gDefaultServiceManagerLock.unlock(); - } - } -} - -// ---------------------------------------------------------------------- - -class BpServiceManager : public BpInterface<IServiceManager> -{ -public: - BpServiceManager(const sp<IBinder>& impl) - : BpInterface<IServiceManager>(impl) - { - } - - virtual sp<IBinder> getService(const String16& name) const - { - unsigned n; - for (n = 0; n < 5; n++){ - sp<IBinder> svc = checkService(name); - if (svc != NULL) return svc; - LOGI("Waiting for sevice %s...\n", String8(name).string()); - sleep(1); - } - return NULL; - } - - virtual sp<IBinder> checkService( const String16& name) const - { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeString16(name); - remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); - return reply.readStrongBinder(); - } - - virtual status_t addService(const String16& name, const sp<IBinder>& service) - { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeString16(name); - data.writeStrongBinder(service); - status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); - return err == NO_ERROR ? reply.readInt32() : err; - } - - virtual Vector<String16> listServices() - { - Vector<String16> res; - int n = 0; - - for (;;) { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeInt32(n++); - status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply); - if (err != NO_ERROR) - break; - res.add(reply.readString16()); - } - return res; - } -}; - -IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnServiceManager::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - //printf("ServiceManager received: "); data.print(); - switch(code) { - case GET_SERVICE_TRANSACTION: { - CHECK_INTERFACE(IServiceManager, data, reply); - String16 which = data.readString16(); - sp<IBinder> b = const_cast<BnServiceManager*>(this)->getService(which); - reply->writeStrongBinder(b); - return NO_ERROR; - } break; - case CHECK_SERVICE_TRANSACTION: { - CHECK_INTERFACE(IServiceManager, data, reply); - String16 which = data.readString16(); - sp<IBinder> b = const_cast<BnServiceManager*>(this)->checkService(which); - reply->writeStrongBinder(b); - return NO_ERROR; - } break; - case ADD_SERVICE_TRANSACTION: { - CHECK_INTERFACE(IServiceManager, data, reply); - String16 which = data.readString16(); - sp<IBinder> b = data.readStrongBinder(); - status_t err = addService(which, b); - reply->writeInt32(err); - return NO_ERROR; - } break; - case LIST_SERVICES_TRANSACTION: { - CHECK_INTERFACE(IServiceManager, data, reply); - Vector<String16> list = listServices(); - const size_t N = list.size(); - reply->writeInt32(N); - for (size_t i=0; i<N; i++) { - reply->writeString16(list[i]); - } - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android - diff --git a/libs/utils/InetAddress.cpp b/libs/utils/InetAddress.cpp deleted file mode 100644 index 39a0a68..0000000 --- a/libs/utils/InetAddress.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Internet address class. -// -#ifdef HAVE_WINSOCK -# include <winsock2.h> -#else -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -//# include <arpa/inet.h> -# include <netdb.h> -#endif - -#include <utils/inet_address.h> -#include <utils/threads.h> -#include <utils/Log.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -using namespace android; - - -/* - * =========================================================================== - * InetAddress - * =========================================================================== - */ - -// lock for the next couple of functions; could tuck into InetAddress -static Mutex* gGHBNLock; - -/* - * Lock/unlock access to the hostent struct returned by gethostbyname(). - */ -static inline void lock_gethostbyname(void) -{ - if (gGHBNLock == NULL) - gGHBNLock = new Mutex; - gGHBNLock->lock(); -} -static inline void unlock_gethostbyname(void) -{ - assert(gGHBNLock != NULL); - gGHBNLock->unlock(); -} - - -/* - * Constructor -- just init members. This is private so that callers - * are required to use getByName(). - */ -InetAddress::InetAddress(void) - : mAddress(NULL), mLength(-1), mName(NULL) -{ -} - -/* - * Destructor -- free address storage. - */ -InetAddress::~InetAddress(void) -{ - delete[] (char*) mAddress; - delete[] mName; -} - -/* - * Copy constructor. - */ -InetAddress::InetAddress(const InetAddress& orig) -{ - *this = orig; // use assignment code -} - -/* - * Assignment operator. - */ -InetAddress& InetAddress::operator=(const InetAddress& addr) -{ - // handle self-assignment - if (this == &addr) - return *this; - // copy mLength and mAddress - mLength = addr.mLength; - if (mLength > 0) { - mAddress = new char[mLength]; - memcpy(mAddress, addr.mAddress, mLength); - LOG(LOG_DEBUG, "socket", - "HEY: copied %d bytes in assignment operator\n", mLength); - } else { - mAddress = NULL; - } - // copy mName - mName = new char[strlen(addr.mName)+1]; - strcpy(mName, addr.mName); - - return *this; -} - -/* - * Create a new object from a name or a dotted-number IP notation. - * - * Returns NULL on failure. - */ -InetAddress* -InetAddress::getByName(const char* host) -{ - InetAddress* newAddr = NULL; - struct sockaddr_in addr; - struct hostent* he; - DurationTimer hostTimer, lockTimer; - - // gethostbyname() isn't reentrant, so we need to lock things until - // we can copy the data out. - lockTimer.start(); - lock_gethostbyname(); - hostTimer.start(); - - he = gethostbyname(host); - if (he == NULL) { - LOG(LOG_WARN, "socket", "WARNING: cannot resolve host %s\n", host); - unlock_gethostbyname(); - return NULL; - } - - memcpy(&addr.sin_addr, he->h_addr, he->h_length); - addr.sin_family = he->h_addrtype; - addr.sin_port = 0; - - // got it, unlock us - hostTimer.stop(); - he = NULL; - unlock_gethostbyname(); - - lockTimer.stop(); - if ((long) lockTimer.durationUsecs() > 100000) { - long lockTime = (long) lockTimer.durationUsecs(); - long hostTime = (long) hostTimer.durationUsecs(); - LOG(LOG_DEBUG, "socket", - "Lookup of %s took %.3fs (gethostbyname=%.3fs lock=%.3fs)\n", - host, lockTime / 1000000.0, hostTime / 1000000.0, - (lockTime - hostTime) / 1000000.0); - } - - // Alloc storage and copy it over. - newAddr = new InetAddress(); - if (newAddr == NULL) - return NULL; - - newAddr->mLength = sizeof(struct sockaddr_in); - newAddr->mAddress = new char[sizeof(struct sockaddr_in)]; - if (newAddr->mAddress == NULL) { - delete newAddr; - return NULL; - } - memcpy(newAddr->mAddress, &addr, newAddr->mLength); - - // Keep this for debug messages. - newAddr->mName = new char[strlen(host)+1]; - if (newAddr->mName == NULL) { - delete newAddr; - return NULL; - } - strcpy(newAddr->mName, host); - - return newAddr; -} - - -/* - * =========================================================================== - * InetSocketAddress - * =========================================================================== - */ - -/* - * Create an address with the host wildcard (INADDR_ANY). - */ -bool InetSocketAddress::create(int port) -{ - assert(mAddress == NULL); - - mAddress = InetAddress::getByName("0.0.0.0"); - if (mAddress == NULL) - return false; - mPort = port; - return true; -} - -/* - * Create address with host and port specified. - */ -bool InetSocketAddress::create(const InetAddress* addr, int port) -{ - assert(mAddress == NULL); - - mAddress = new InetAddress(*addr); // make a copy - if (mAddress == NULL) - return false; - mPort = port; - return true; -} - -/* - * Create address with host and port specified. - */ -bool InetSocketAddress::create(const char* host, int port) -{ - assert(mAddress == NULL); - - mAddress = InetAddress::getByName(host); - if (mAddress == NULL) - return false; - mPort = port; - return true; -} - diff --git a/libs/utils/LogSocket.cpp b/libs/utils/LogSocket.cpp deleted file mode 100644 index 55c1b99..0000000 --- a/libs/utils/LogSocket.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#ifndef HAVE_WINSOCK -//#define SOCKETLOG -#endif - -#ifdef SOCKETLOG - -#define LOG_TAG "SOCKETLOG" - -#include <string.h> -#include <cutils/log.h> -#include "utils/LogSocket.h" -#include "utils/logger.h" -#include "cutils/hashmap.h" - -// defined in //device/data/etc/event-log-tags -#define SOCKET_CLOSE_LOG 51000 - -static Hashmap* statsMap = NULL; - -#define LOG_LIST_NUMBER 5 - -typedef struct SocketStats { - int fd; - unsigned int send; - unsigned int recv; - unsigned int ip; - unsigned short port; - short reason; -}SocketStats; - -SocketStats *get_socket_stats(int fd) { - if (statsMap == NULL) { - statsMap = hashmapCreate(8, &hashmapIntHash, &hashmapIntEquals); - } - - SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd); - if (s == NULL) { - // LOGD("create SocketStats for fd %d", fd); - s = (SocketStats*) malloc(sizeof(SocketStats)); - memset(s, 0, sizeof(SocketStats)); - s->fd = fd; - hashmapPut(statsMap, &s->fd, s); - } - return s; -} - -void log_socket_connect(int fd, unsigned int ip, unsigned short port) { - // LOGD("log_socket_connect for fd %d ip %d port%d", fd, ip, port); - SocketStats *s = get_socket_stats(fd); - s->ip = ip; - s->port = port; -} - -void add_send_stats(int fd, int send) { - if (send <=0) { - LOGE("add_send_stats send %d", send); - return; - } - SocketStats *s = get_socket_stats(fd); - s->send += send; - // LOGD("add_send_stats for fd %d ip %d port%d", fd, s->ip, s->port); -} - -void add_recv_stats(int fd, int recv) { - if (recv <=0) { - LOGE("add_recv_stats recv %d", recv); - return; - } - SocketStats *s = get_socket_stats(fd); - s->recv += recv; - // LOGD("add_recv_stats for fd %d ip %d port%d", fd, s->ip, s->port); -} - -char* put_int(char* buf, int value) { - *buf = EVENT_TYPE_INT; - buf++; - memcpy(buf, &value, sizeof(int)); - return buf + sizeof(int); -} - -void log_socket_close(int fd, short reason) { - if (statsMap) { - SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd); - if (s != NULL) { - if (s->send != 0 || s->recv != 0) { - s->reason = reason; - // 5 int + list type need 2 bytes - char buf[LOG_LIST_NUMBER * 5 + 2]; - buf[0] = EVENT_TYPE_LIST; - buf[1] = LOG_LIST_NUMBER; - char* writePos = buf + 2; - writePos = put_int(writePos, s->send); - writePos = put_int(writePos, s->recv); - writePos = put_int(writePos, s->ip); - writePos = put_int(writePos, s->port); - writePos = put_int(writePos, s->reason); - - android_bWriteLog(SOCKET_CLOSE_LOG, buf, sizeof(buf)); - // LOGD("send %d recv %d reason %d", s->send, s->recv, s->reason); - } - hashmapRemove(statsMap, &s->fd); - free(s); - } - } -} - -#else -void add_send_stats(int fd, int send) {} -void add_recv_stats(int fd, int recv) {} -void log_socket_close(int fd, short reason) {} -void log_socket_connect(int fd, unsigned int ip, unsigned short port) {} -#endif diff --git a/libs/utils/MODULE_LICENSE_APACHE2 b/libs/utils/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/libs/utils/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/libs/utils/MemoryBase.cpp b/libs/utils/MemoryBase.cpp deleted file mode 100644 index f25e11c..0000000 --- a/libs/utils/MemoryBase.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include <stdlib.h> -#include <stdint.h> - -#include <utils/MemoryBase.h> - - -namespace android { - -// --------------------------------------------------------------------------- - -MemoryBase::MemoryBase(const sp<IMemoryHeap>& heap, - ssize_t offset, size_t size) - : mSize(size), mOffset(offset), mHeap(heap) -{ -} - -sp<IMemoryHeap> MemoryBase::getMemory(ssize_t* offset, size_t* size) const -{ - if (offset) *offset = mOffset; - if (size) *size = mSize; - return mHeap; -} - -MemoryBase::~MemoryBase() -{ -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/utils/MemoryDealer.cpp b/libs/utils/MemoryDealer.cpp deleted file mode 100644 index cf8201b..0000000 --- a/libs/utils/MemoryDealer.cpp +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "MemoryDealer" - -#include <utils/MemoryDealer.h> - -#include <utils/Log.h> -#include <utils/IPCThreadState.h> -#include <utils/SortedVector.h> -#include <utils/String8.h> -#include <utils/MemoryBase.h> - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/file.h> - -namespace android { - - -// ---------------------------------------------------------------------------- - -class SimpleMemory : public MemoryBase { -public: - SimpleMemory(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size); - virtual ~SimpleMemory(); -}; - - -// ---------------------------------------------------------------------------- - -MemoryDealer::Allocation::Allocation( - const sp<MemoryDealer>& dealer, ssize_t offset, size_t size, - const sp<IMemory>& memory) - : mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory) -{ -} - -MemoryDealer::Allocation::~Allocation() -{ - if (mSize) { - /* NOTE: it's VERY important to not free allocations of size 0 because - * they're special as they don't have any record in the allocator - * and could alias some real allocation (their offset is zero). */ - mDealer->deallocate(mOffset); - } -} - -sp<IMemoryHeap> MemoryDealer::Allocation::getMemory( - ssize_t* offset, size_t* size) const -{ - return mMemory->getMemory(offset, size); -} - -// ---------------------------------------------------------------------------- - -MemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name) - : mHeap(new SharedHeap(size, flags, name)), - mAllocator(new SimpleBestFitAllocator(size)) -{ -} - -MemoryDealer::MemoryDealer(const sp<HeapInterface>& heap) - : mHeap(heap), - mAllocator(new SimpleBestFitAllocator(heap->virtualSize())) -{ -} - -MemoryDealer::MemoryDealer( const sp<HeapInterface>& heap, - const sp<AllocatorInterface>& allocator) - : mHeap(heap), mAllocator(allocator) -{ -} - -MemoryDealer::~MemoryDealer() -{ -} - -sp<IMemory> MemoryDealer::allocate(size_t size, uint32_t flags) -{ - sp<IMemory> memory; - const ssize_t offset = allocator()->allocate(size, flags); - if (offset >= 0) { - sp<IMemory> new_memory = heap()->mapMemory(offset, size); - if (new_memory != 0) { - memory = new Allocation(this, offset, size, new_memory); - } else { - LOGE("couldn't map [%8x, %d]", offset, size); - if (size) { - /* NOTE: it's VERY important to not free allocations of size 0 - * because they're special as they don't have any record in the - * allocator and could alias some real allocation - * (their offset is zero). */ - allocator()->deallocate(offset); - } - } - } - return memory; -} - -void MemoryDealer::deallocate(size_t offset) -{ - allocator()->deallocate(offset); -} - -void MemoryDealer::dump(const char* what, uint32_t flags) const -{ - allocator()->dump(what, flags); -} - -const sp<HeapInterface>& MemoryDealer::heap() const { - return mHeap; -} - -const sp<AllocatorInterface>& MemoryDealer::allocator() const { - return mAllocator; -} - -// ---------------------------------------------------------------------------- - -// align all the memory blocks on a cache-line boundary -const int SimpleBestFitAllocator::kMemoryAlign = 32; - -SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) -{ - size_t pagesize = getpagesize(); - mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); - - chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); - mList.insertHead(node); -} - -SimpleBestFitAllocator::~SimpleBestFitAllocator() -{ - while(!mList.isEmpty()) { - delete mList.remove(mList.head()); - } -} - -size_t SimpleBestFitAllocator::size() const -{ - return mHeapSize; -} - -size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) -{ - Mutex::Autolock _l(mLock); - ssize_t offset = alloc(size, flags); - return offset; -} - -status_t SimpleBestFitAllocator::deallocate(size_t offset) -{ - Mutex::Autolock _l(mLock); - chunk_t const * const freed = dealloc(offset); - if (freed) { - return NO_ERROR; - } - return NAME_NOT_FOUND; -} - -ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) -{ - if (size == 0) { - return 0; - } - size = (size + kMemoryAlign-1) / kMemoryAlign; - chunk_t* free_chunk = 0; - chunk_t* cur = mList.head(); - - size_t pagesize = getpagesize(); - while (cur) { - int extra = 0; - if (flags & PAGE_ALIGNED) - extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; - - // best fit - if (cur->free && (cur->size >= (size+extra))) { - if ((!free_chunk) || (cur->size < free_chunk->size)) { - free_chunk = cur; - } - if (cur->size == size) { - break; - } - } - cur = cur->next; - } - - if (free_chunk) { - const size_t free_size = free_chunk->size; - free_chunk->free = 0; - free_chunk->size = size; - if (free_size > size) { - int extra = 0; - if (flags & PAGE_ALIGNED) - extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; - if (extra) { - chunk_t* split = new chunk_t(free_chunk->start, extra); - free_chunk->start += extra; - mList.insertBefore(free_chunk, split); - } - - LOGE_IF((flags&PAGE_ALIGNED) && - ((free_chunk->start*kMemoryAlign)&(pagesize-1)), - "PAGE_ALIGNED requested, but page is not aligned!!!"); - - const ssize_t tail_free = free_size - (size+extra); - if (tail_free > 0) { - chunk_t* split = new chunk_t( - free_chunk->start + free_chunk->size, tail_free); - mList.insertAfter(free_chunk, split); - } - } - return (free_chunk->start)*kMemoryAlign; - } - return NO_MEMORY; -} - -SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) -{ - start = start / kMemoryAlign; - chunk_t* cur = mList.head(); - while (cur) { - if (cur->start == start) { - LOG_FATAL_IF(cur->free, - "block at offset 0x%08lX of size 0x%08lX already freed", - cur->start*kMemoryAlign, cur->size*kMemoryAlign); - - // merge freed blocks together - chunk_t* freed = cur; - cur->free = 1; - do { - chunk_t* const p = cur->prev; - chunk_t* const n = cur->next; - if (p && (p->free || !cur->size)) { - freed = p; - p->size += cur->size; - mList.remove(cur); - delete cur; - } - cur = n; - } while (cur && cur->free); - - #ifndef NDEBUG - if (!freed->free) { - dump_l("dealloc (!freed->free)"); - } - #endif - LOG_FATAL_IF(!freed->free, - "freed block at offset 0x%08lX of size 0x%08lX is not free!", - freed->start * kMemoryAlign, freed->size * kMemoryAlign); - - return freed; - } - cur = cur->next; - } - return 0; -} - -void SimpleBestFitAllocator::dump(const char* what, uint32_t flags) const -{ - Mutex::Autolock _l(mLock); - dump_l(what, flags); -} - -void SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const -{ - String8 result; - dump_l(result, what, flags); - LOGD("%s", result.string()); -} - -void SimpleBestFitAllocator::dump(String8& result, - const char* what, uint32_t flags) const -{ - Mutex::Autolock _l(mLock); - dump_l(result, what, flags); -} - -void SimpleBestFitAllocator::dump_l(String8& result, - const char* what, uint32_t flags) const -{ - size_t size = 0; - int32_t i = 0; - chunk_t const* cur = mList.head(); - - const size_t SIZE = 256; - char buffer[SIZE]; - snprintf(buffer, SIZE, " %s (%p, size=%u)\n", - what, this, (unsigned int)mHeapSize); - - result.append(buffer); - - while (cur) { - const char* errs[] = {"", "| link bogus NP", - "| link bogus PN", "| link bogus NP+PN" }; - int np = ((cur->next) && cur->next->prev != cur) ? 1 : 0; - int pn = ((cur->prev) && cur->prev->next != cur) ? 2 : 0; - - snprintf(buffer, SIZE, " %3u: %08x | 0x%08X | 0x%08X | %s %s\n", - i, int(cur), int(cur->start*kMemoryAlign), - int(cur->size*kMemoryAlign), - int(cur->free) ? "F" : "A", - errs[np|pn]); - - result.append(buffer); - - if (!cur->free) - size += cur->size*kMemoryAlign; - - i++; - cur = cur->next; - } - snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size/1024)); - result.append(buffer); -} - -// ---------------------------------------------------------------------------- - - -SharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name) - : MemoryHeapBase(size, flags, name) -{ -} - -SharedHeap::~SharedHeap() -{ -} - -sp<IMemory> SharedHeap::mapMemory(size_t offset, size_t size) -{ - return new SimpleMemory(this, offset, size); -} - - -SimpleMemory::SimpleMemory(const sp<IMemoryHeap>& heap, - ssize_t offset, size_t size) - : MemoryBase(heap, offset, size) -{ -#ifndef NDEBUG - void* const start_ptr = (void*)(intptr_t(heap->base()) + offset); - memset(start_ptr, 0xda, size); -#endif -} - -SimpleMemory::~SimpleMemory() -{ - size_t freedOffset = getOffset(); - size_t freedSize = getSize(); - - // keep the size to unmap in excess - size_t pagesize = getpagesize(); - size_t start = freedOffset; - size_t end = start + freedSize; - start &= ~(pagesize-1); - end = (end + pagesize-1) & ~(pagesize-1); - - // give back to the kernel the pages we don't need - size_t free_start = freedOffset; - size_t free_end = free_start + freedSize; - if (start < free_start) - start = free_start; - if (end > free_end) - end = free_end; - start = (start + pagesize-1) & ~(pagesize-1); - end &= ~(pagesize-1); - - if (start < end) { - void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start); - size_t size = end-start; - -#ifndef NDEBUG - memset(start_ptr, 0xdf, size); -#endif - - // MADV_REMOVE is not defined on Dapper based Goobuntu -#ifdef MADV_REMOVE - if (size) { - int err = madvise(start_ptr, size, MADV_REMOVE); - LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s", - start_ptr, size, err<0 ? strerror(errno) : "Ok"); - } -#endif - } -} - -}; // namespace android diff --git a/libs/utils/MemoryHeapBase.cpp b/libs/utils/MemoryHeapBase.cpp deleted file mode 100644 index 8251728..0000000 --- a/libs/utils/MemoryHeapBase.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "MemoryHeapBase" - -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <cutils/log.h> -#include <cutils/ashmem.h> -#include <cutils/atomic.h> - -#include <utils/MemoryHeapBase.h> - -#if HAVE_ANDROID_OS -#include <linux/android_pmem.h> -#endif - - -namespace android { - -// --------------------------------------------------------------------------- - -MemoryHeapBase::MemoryHeapBase() - : mFD(-1), mSize(0), mBase(MAP_FAILED), - mDevice(NULL), mNeedUnmap(false) -{ -} - -MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) - : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), - mDevice(0), mNeedUnmap(false) -{ - const size_t pagesize = getpagesize(); - size = ((size + pagesize-1) & ~(pagesize-1)); - int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size); - LOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno)); - if (fd >= 0) { - if (mapfd(fd, size) == NO_ERROR) { - if (flags & READ_ONLY) { - ashmem_set_prot_region(fd, PROT_READ); - } - } - } -} - -MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags) - : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), - mDevice(0), mNeedUnmap(false) -{ - int fd = open(device, O_RDWR); - LOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno)); - if (fd >= 0) { - const size_t pagesize = getpagesize(); - size = ((size + pagesize-1) & ~(pagesize-1)); - if (mapfd(fd, size) == NO_ERROR) { - mDevice = device; - } - } -} - -MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags) - : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), - mDevice(0), mNeedUnmap(false) -{ - const size_t pagesize = getpagesize(); - size = ((size + pagesize-1) & ~(pagesize-1)); - mapfd(dup(fd), size); -} - -status_t MemoryHeapBase::init(int fd, void *base, int size, int flags, const char* device) -{ - if (mFD != -1) { - return INVALID_OPERATION; - } - mFD = fd; - mBase = base; - mSize = size; - mFlags = flags; - mDevice = device; - return NO_ERROR; -} - -status_t MemoryHeapBase::mapfd(int fd, size_t size) -{ - if (size == 0) { - // try to figure out the size automatically -#if HAVE_ANDROID_OS - // first try the PMEM ioctl - pmem_region reg; - int err = ioctl(fd, PMEM_GET_TOTAL_SIZE, ®); - if (err == 0) - size = reg.len; -#endif - if (size == 0) { // try fstat - struct stat sb; - if (fstat(fd, &sb) == 0) - size = sb.st_size; - } - // if it didn't work, let mmap() fail. - } - - if ((mFlags & DONT_MAP_LOCALLY) == 0) { - void* base = (uint8_t*)mmap(0, size, - PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) { - LOGE("mmap(fd=%d, size=%u) failed (%s)", - fd, uint32_t(size), strerror(errno)); - close(fd); - return -errno; - } - //LOGD("mmap(fd=%d, base=%p, size=%lu)", fd, base, size); - mBase = base; - mNeedUnmap = true; - } else { - mBase = 0; // not MAP_FAILED - mNeedUnmap = false; - } - mFD = fd; - mSize = size; - return NO_ERROR; -} - -MemoryHeapBase::~MemoryHeapBase() -{ - dispose(); -} - -void MemoryHeapBase::dispose() -{ - int fd = android_atomic_or(-1, &mFD); - if (fd >= 0) { - if (mNeedUnmap) { - //LOGD("munmap(fd=%d, base=%p, size=%lu)", fd, mBase, mSize); - munmap(mBase, mSize); - } - mBase = 0; - mSize = 0; - close(fd); - } -} - -int MemoryHeapBase::getHeapID() const { - return mFD; -} - -void* MemoryHeapBase::getBase() const { - return mBase; -} - -size_t MemoryHeapBase::getSize() const { - return mSize; -} - -uint32_t MemoryHeapBase::getFlags() const { - return mFlags; -} - -const char* MemoryHeapBase::getDevice() const { - return mDevice; -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/utils/MemoryHeapPmem.cpp b/libs/utils/MemoryHeapPmem.cpp deleted file mode 100644 index eba2b30..0000000 --- a/libs/utils/MemoryHeapPmem.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "MemoryHeapPmem" - -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <cutils/log.h> - -#include <utils/MemoryHeapPmem.h> -#include <utils/MemoryHeapBase.h> - -#if HAVE_ANDROID_OS -#include <linux/android_pmem.h> -#endif - -namespace android { - -// --------------------------------------------------------------------------- - -MemoryHeapPmem::MemoryPmem::MemoryPmem(const sp<MemoryHeapPmem>& heap) - : BnMemory(), mClientHeap(heap) -{ -} - -MemoryHeapPmem::MemoryPmem::~MemoryPmem() { - if (mClientHeap != NULL) { - mClientHeap->remove(this); - } -} - -// --------------------------------------------------------------------------- - -class SubRegionMemory : public MemoryHeapPmem::MemoryPmem { -public: - SubRegionMemory(const sp<MemoryHeapPmem>& heap, ssize_t offset, size_t size); - virtual ~SubRegionMemory(); - virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const; -private: - friend class MemoryHeapPmem; - void revoke(); - size_t mSize; - ssize_t mOffset; -}; - -SubRegionMemory::SubRegionMemory(const sp<MemoryHeapPmem>& heap, - ssize_t offset, size_t size) - : MemoryHeapPmem::MemoryPmem(heap), mSize(size), mOffset(offset) -{ -#ifndef NDEBUG - void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + offset); - memset(start_ptr, 0xda, size); -#endif - -#if HAVE_ANDROID_OS - if (size > 0) { - const size_t pagesize = getpagesize(); - size = (size + pagesize-1) & ~(pagesize-1); - int our_fd = heap->heapID(); - struct pmem_region sub = { offset, size }; - int err = ioctl(our_fd, PMEM_MAP, &sub); - LOGE_IF(err<0, "PMEM_MAP failed (%s), " - "mFD=%d, sub.offset=%lu, sub.size=%lu", - strerror(errno), our_fd, sub.offset, sub.len); -} -#endif -} - -sp<IMemoryHeap> SubRegionMemory::getMemory(ssize_t* offset, size_t* size) const -{ - if (offset) *offset = mOffset; - if (size) *size = mSize; - return getHeap(); -} - -SubRegionMemory::~SubRegionMemory() -{ - revoke(); -} - - -void SubRegionMemory::revoke() -{ - // NOTE: revoke() doesn't need to be protected by a lock because it - // can only be called from MemoryHeapPmem::revoke(), which means - // that we can't be in ~SubRegionMemory(), or in ~SubRegionMemory(), - // which means MemoryHeapPmem::revoke() wouldn't have been able to - // promote() it. - -#if HAVE_ANDROID_OS - if (mSize != NULL) { - const sp<MemoryHeapPmem>& heap(getHeap()); - int our_fd = heap->heapID(); - struct pmem_region sub; - sub.offset = mOffset; - sub.len = mSize; - int err = ioctl(our_fd, PMEM_UNMAP, &sub); - LOGE_IF(err<0, "PMEM_UNMAP failed (%s), " - "mFD=%d, sub.offset=%lu, sub.size=%lu", - strerror(errno), our_fd, sub.offset, sub.len); - mSize = 0; - } -#endif -} - -// --------------------------------------------------------------------------- - -MemoryHeapPmem::MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap, - uint32_t flags) - : HeapInterface(), MemoryHeapBase() -{ - char const * const device = pmemHeap->getDevice(); -#if HAVE_ANDROID_OS - if (device) { - int fd = open(device, O_RDWR); - LOGE_IF(fd<0, "couldn't open %s (%s)", device, strerror(errno)); - if (fd >= 0) { - int err = ioctl(fd, PMEM_CONNECT, pmemHeap->heapID()); - if (err < 0) { - LOGE("PMEM_CONNECT failed (%s), mFD=%d, sub-fd=%d", - strerror(errno), fd, pmemHeap->heapID()); - close(fd); - } else { - // everything went well... - mParentHeap = pmemHeap; - MemoryHeapBase::init(fd, - pmemHeap->getBase(), - pmemHeap->getSize(), - pmemHeap->getFlags() | flags, - device); - } - } - } -#else - mParentHeap = pmemHeap; - MemoryHeapBase::init( - dup(pmemHeap->heapID()), - pmemHeap->getBase(), - pmemHeap->getSize(), - pmemHeap->getFlags() | flags, - device); -#endif -} - -MemoryHeapPmem::~MemoryHeapPmem() -{ -} - -sp<IMemory> MemoryHeapPmem::mapMemory(size_t offset, size_t size) -{ - sp<MemoryPmem> memory = createMemory(offset, size); - if (memory != 0) { - Mutex::Autolock _l(mLock); - mAllocations.add(memory); - } - return memory; -} - -sp<MemoryHeapPmem::MemoryPmem> MemoryHeapPmem::createMemory( - size_t offset, size_t size) -{ - sp<SubRegionMemory> memory; - if (heapID() > 0) - memory = new SubRegionMemory(this, offset, size); - return memory; -} - -status_t MemoryHeapPmem::slap() -{ -#if HAVE_ANDROID_OS - size_t size = getSize(); - const size_t pagesize = getpagesize(); - size = (size + pagesize-1) & ~(pagesize-1); - int our_fd = getHeapID(); - struct pmem_region sub = { 0, size }; - int err = ioctl(our_fd, PMEM_MAP, &sub); - LOGE_IF(err<0, "PMEM_MAP failed (%s), " - "mFD=%d, sub.offset=%lu, sub.size=%lu", - strerror(errno), our_fd, sub.offset, sub.len); - return -errno; -#else - return NO_ERROR; -#endif -} - -status_t MemoryHeapPmem::unslap() -{ -#if HAVE_ANDROID_OS - size_t size = getSize(); - const size_t pagesize = getpagesize(); - size = (size + pagesize-1) & ~(pagesize-1); - int our_fd = getHeapID(); - struct pmem_region sub = { 0, size }; - int err = ioctl(our_fd, PMEM_UNMAP, &sub); - LOGE_IF(err<0, "PMEM_UNMAP failed (%s), " - "mFD=%d, sub.offset=%lu, sub.size=%lu", - strerror(errno), our_fd, sub.offset, sub.len); - return -errno; -#else - return NO_ERROR; -#endif -} - -void MemoryHeapPmem::revoke() -{ - SortedVector< wp<MemoryPmem> > allocations; - - { // scope for lock - Mutex::Autolock _l(mLock); - allocations = mAllocations; - } - - ssize_t count = allocations.size(); - for (ssize_t i=0 ; i<count ; i++) { - sp<MemoryPmem> memory(allocations[i].promote()); - if (memory != 0) - memory->revoke(); - } -} - -void MemoryHeapPmem::remove(const wp<MemoryPmem>& memory) -{ - Mutex::Autolock _l(mLock); - mAllocations.remove(memory); -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/utils/NOTICE b/libs/utils/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/libs/utils/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/libs/utils/Parcel.cpp b/libs/utils/Parcel.cpp deleted file mode 100644 index 0f4b647..0000000 --- a/libs/utils/Parcel.cpp +++ /dev/null @@ -1,1377 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Parcel" -//#define LOG_NDEBUG 0 - -#include <utils/Parcel.h> - -#include <utils/Binder.h> -#include <utils/BpBinder.h> -#include <utils/Debug.h> -#include <utils/ProcessState.h> -#include <utils/Log.h> -#include <utils/String8.h> -#include <utils/String16.h> -#include <utils/TextOutput.h> -#include <utils/misc.h> - -#include <private/utils/binder_module.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> - -#ifndef INT32_MAX -#define INT32_MAX ((int32_t)(2147483647)) -#endif - -#define LOG_REFS(...) -//#define LOG_REFS(...) LOG(LOG_DEBUG, "Parcel", __VA_ARGS__) - -// --------------------------------------------------------------------------- - -#define PAD_SIZE(s) (((s)+3)&~3) - -// XXX This can be made public if we want to provide -// support for typed data. -struct small_flat_data -{ - uint32_t type; - uint32_t data; -}; - -namespace android { - -void acquire_object(const sp<ProcessState>& proc, - const flat_binder_object& obj, const void* who) -{ - switch (obj.type) { - case BINDER_TYPE_BINDER: - if (obj.binder) { - LOG_REFS("Parcel %p acquiring reference on local %p", who, obj.cookie); - static_cast<IBinder*>(obj.cookie)->incStrong(who); - } - return; - case BINDER_TYPE_WEAK_BINDER: - if (obj.binder) - static_cast<RefBase::weakref_type*>(obj.binder)->incWeak(who); - return; - case BINDER_TYPE_HANDLE: { - const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle); - if (b != NULL) { - LOG_REFS("Parcel %p acquiring reference on remote %p", who, b.get()); - b->incStrong(who); - } - return; - } - case BINDER_TYPE_WEAK_HANDLE: { - const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle); - if (b != NULL) b.get_refs()->incWeak(who); - return; - } - case BINDER_TYPE_FD: { - // intentionally blank -- nothing to do to acquire this, but we do - // recognize it as a legitimate object type. - return; - } - } - - LOGD("Invalid object type 0x%08lx", obj.type); -} - -void release_object(const sp<ProcessState>& proc, - const flat_binder_object& obj, const void* who) -{ - switch (obj.type) { - case BINDER_TYPE_BINDER: - if (obj.binder) { - LOG_REFS("Parcel %p releasing reference on local %p", who, obj.cookie); - static_cast<IBinder*>(obj.cookie)->decStrong(who); - } - return; - case BINDER_TYPE_WEAK_BINDER: - if (obj.binder) - static_cast<RefBase::weakref_type*>(obj.binder)->decWeak(who); - return; - case BINDER_TYPE_HANDLE: { - const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle); - if (b != NULL) { - LOG_REFS("Parcel %p releasing reference on remote %p", who, b.get()); - b->decStrong(who); - } - return; - } - case BINDER_TYPE_WEAK_HANDLE: { - const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle); - if (b != NULL) b.get_refs()->decWeak(who); - return; - } - case BINDER_TYPE_FD: { - if (obj.cookie != (void*)0) close(obj.handle); - return; - } - } - - LOGE("Invalid object type 0x%08lx", obj.type); -} - -inline static status_t finish_flatten_binder( - const sp<IBinder>& binder, const flat_binder_object& flat, Parcel* out) -{ - return out->writeObject(flat, false); -} - -status_t flatten_binder(const sp<ProcessState>& proc, - const sp<IBinder>& binder, Parcel* out) -{ - flat_binder_object obj; - - obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - if (binder != NULL) { - IBinder *local = binder->localBinder(); - if (!local) { - BpBinder *proxy = binder->remoteBinder(); - if (proxy == NULL) { - LOGE("null proxy"); - } - const int32_t handle = proxy ? proxy->handle() : 0; - obj.type = BINDER_TYPE_HANDLE; - obj.handle = handle; - obj.cookie = NULL; - } else { - obj.type = BINDER_TYPE_BINDER; - obj.binder = local->getWeakRefs(); - obj.cookie = local; - } - } else { - obj.type = BINDER_TYPE_BINDER; - obj.binder = NULL; - obj.cookie = NULL; - } - - return finish_flatten_binder(binder, obj, out); -} - -status_t flatten_binder(const sp<ProcessState>& proc, - const wp<IBinder>& binder, Parcel* out) -{ - flat_binder_object obj; - - obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - if (binder != NULL) { - sp<IBinder> real = binder.promote(); - if (real != NULL) { - IBinder *local = real->localBinder(); - if (!local) { - BpBinder *proxy = real->remoteBinder(); - if (proxy == NULL) { - LOGE("null proxy"); - } - const int32_t handle = proxy ? proxy->handle() : 0; - obj.type = BINDER_TYPE_WEAK_HANDLE; - obj.handle = handle; - obj.cookie = NULL; - } else { - obj.type = BINDER_TYPE_WEAK_BINDER; - obj.binder = binder.get_refs(); - obj.cookie = binder.unsafe_get(); - } - return finish_flatten_binder(real, obj, out); - } - - // XXX How to deal? In order to flatten the given binder, - // we need to probe it for information, which requires a primary - // reference... but we don't have one. - // - // The OpenBinder implementation uses a dynamic_cast<> here, - // but we can't do that with the different reference counting - // implementation we are using. - LOGE("Unable to unflatten Binder weak reference!"); - obj.type = BINDER_TYPE_BINDER; - obj.binder = NULL; - obj.cookie = NULL; - return finish_flatten_binder(NULL, obj, out); - - } else { - obj.type = BINDER_TYPE_BINDER; - obj.binder = NULL; - obj.cookie = NULL; - return finish_flatten_binder(NULL, obj, out); - } -} - -inline static status_t finish_unflatten_binder( - BpBinder* proxy, const flat_binder_object& flat, const Parcel& in) -{ - return NO_ERROR; -} - -status_t unflatten_binder(const sp<ProcessState>& proc, - const Parcel& in, sp<IBinder>* out) -{ - const flat_binder_object* flat = in.readObject(false); - - if (flat) { - switch (flat->type) { - case BINDER_TYPE_BINDER: - *out = static_cast<IBinder*>(flat->cookie); - return finish_unflatten_binder(NULL, *flat, in); - case BINDER_TYPE_HANDLE: - *out = proc->getStrongProxyForHandle(flat->handle); - return finish_unflatten_binder( - static_cast<BpBinder*>(out->get()), *flat, in); - } - } - return BAD_TYPE; -} - -status_t unflatten_binder(const sp<ProcessState>& proc, - const Parcel& in, wp<IBinder>* out) -{ - const flat_binder_object* flat = in.readObject(false); - - if (flat) { - switch (flat->type) { - case BINDER_TYPE_BINDER: - *out = static_cast<IBinder*>(flat->cookie); - return finish_unflatten_binder(NULL, *flat, in); - case BINDER_TYPE_WEAK_BINDER: - if (flat->binder != NULL) { - out->set_object_and_refs( - static_cast<IBinder*>(flat->cookie), - static_cast<RefBase::weakref_type*>(flat->binder)); - } else { - *out = NULL; - } - return finish_unflatten_binder(NULL, *flat, in); - case BINDER_TYPE_HANDLE: - case BINDER_TYPE_WEAK_HANDLE: - *out = proc->getWeakProxyForHandle(flat->handle); - return finish_unflatten_binder( - static_cast<BpBinder*>(out->unsafe_get()), *flat, in); - } - } - return BAD_TYPE; -} - -// --------------------------------------------------------------------------- - -Parcel::Parcel() -{ - initState(); -} - -Parcel::~Parcel() -{ - freeDataNoInit(); -} - -const uint8_t* Parcel::data() const -{ - return mData; -} - -size_t Parcel::dataSize() const -{ - return (mDataSize > mDataPos ? mDataSize : mDataPos); -} - -size_t Parcel::dataAvail() const -{ - // TODO: decide what to do about the possibility that this can - // report an available-data size that exceeds a Java int's max - // positive value, causing havoc. Fortunately this will only - // happen if someone constructs a Parcel containing more than two - // gigabytes of data, which on typical phone hardware is simply - // not possible. - return dataSize() - dataPosition(); -} - -size_t Parcel::dataPosition() const -{ - return mDataPos; -} - -size_t Parcel::dataCapacity() const -{ - return mDataCapacity; -} - -status_t Parcel::setDataSize(size_t size) -{ - status_t err; - err = continueWrite(size); - if (err == NO_ERROR) { - mDataSize = size; - LOGV("setDataSize Setting data size of %p to %d\n", this, mDataSize); - } - return err; -} - -void Parcel::setDataPosition(size_t pos) const -{ - mDataPos = pos; - mNextObjectHint = 0; -} - -status_t Parcel::setDataCapacity(size_t size) -{ - if (size > mDataSize) return continueWrite(size); - return NO_ERROR; -} - -status_t Parcel::setData(const uint8_t* buffer, size_t len) -{ - status_t err = restartWrite(len); - if (err == NO_ERROR) { - memcpy(const_cast<uint8_t*>(data()), buffer, len); - mDataSize = len; - mFdsKnown = false; - } - return err; -} - -status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len) -{ - const sp<ProcessState> proc(ProcessState::self()); - status_t err; - uint8_t *data = parcel->mData; - size_t *objects = parcel->mObjects; - size_t size = parcel->mObjectsSize; - int startPos = mDataPos; - int firstIndex = -1, lastIndex = -2; - - if (len == 0) { - return NO_ERROR; - } - - // range checks against the source parcel size - if ((offset > parcel->mDataSize) - || (len > parcel->mDataSize) - || (offset + len > parcel->mDataSize)) { - return BAD_VALUE; - } - - // Count objects in range - for (int i = 0; i < (int) size; i++) { - size_t off = objects[i]; - if ((off >= offset) && (off < offset + len)) { - if (firstIndex == -1) { - firstIndex = i; - } - lastIndex = i; - } - } - int numObjects = lastIndex - firstIndex + 1; - - // grow data - err = growData(len); - if (err != NO_ERROR) { - return err; - } - - // append data - memcpy(mData + mDataPos, data + offset, len); - mDataPos += len; - mDataSize += len; - - if (numObjects > 0) { - // grow objects - if (mObjectsCapacity < mObjectsSize + numObjects) { - int newSize = ((mObjectsSize + numObjects)*3)/2; - size_t *objects = - (size_t*)realloc(mObjects, newSize*sizeof(size_t)); - if (objects == (size_t*)0) { - return NO_MEMORY; - } - mObjects = objects; - mObjectsCapacity = newSize; - } - - // append and acquire objects - int idx = mObjectsSize; - for (int i = firstIndex; i <= lastIndex; i++) { - size_t off = objects[i] - offset + startPos; - mObjects[idx++] = off; - mObjectsSize++; - - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(mData + off); - acquire_object(proc, *flat, this); - - // take note if the object is a file descriptor - if (flat->type == BINDER_TYPE_FD) { - mHasFds = mFdsKnown = true; - } - } - } - - return NO_ERROR; -} - -bool Parcel::hasFileDescriptors() const -{ - if (!mFdsKnown) { - scanForFds(); - } - return mHasFds; -} - -status_t Parcel::writeInterfaceToken(const String16& interface) -{ - // currently the interface identification token is just its name as a string - return writeString16(interface); -} - -bool Parcel::enforceInterface(const String16& interface) const -{ - String16 str = readString16(); - if (str == interface) { - return true; - } else { - LOGW("**** enforceInterface() expected '%s' but read '%s'\n", - String8(interface).string(), String8(str).string()); - return false; - } -} - -const size_t* Parcel::objects() const -{ - return mObjects; -} - -size_t Parcel::objectsCount() const -{ - return mObjectsSize; -} - -status_t Parcel::errorCheck() const -{ - return mError; -} - -void Parcel::setError(status_t err) -{ - mError = err; -} - -status_t Parcel::finishWrite(size_t len) -{ - //printf("Finish write of %d\n", len); - mDataPos += len; - LOGV("finishWrite Setting data pos of %p to %d\n", this, mDataPos); - if (mDataPos > mDataSize) { - mDataSize = mDataPos; - LOGV("finishWrite Setting data size of %p to %d\n", this, mDataSize); - } - //printf("New pos=%d, size=%d\n", mDataPos, mDataSize); - return NO_ERROR; -} - -status_t Parcel::writeUnpadded(const void* data, size_t len) -{ - size_t end = mDataPos + len; - if (end < mDataPos) { - // integer overflow - return BAD_VALUE; - } - - if (end <= mDataCapacity) { -restart_write: - memcpy(mData+mDataPos, data, len); - return finishWrite(len); - } - - status_t err = growData(len); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::write(const void* data, size_t len) -{ - void* const d = writeInplace(len); - if (d) { - memcpy(d, data, len); - return NO_ERROR; - } - return mError; -} - -void* Parcel::writeInplace(size_t len) -{ - const size_t padded = PAD_SIZE(len); - - // sanity check for integer overflow - if (mDataPos+padded < mDataPos) { - return NULL; - } - - if ((mDataPos+padded) <= mDataCapacity) { -restart_write: - //printf("Writing %ld bytes, padded to %ld\n", len, padded); - uint8_t* const data = mData+mDataPos; - - // Need to pad at end? - if (padded != len) { -#if BYTE_ORDER == BIG_ENDIAN - static const uint32_t mask[4] = { - 0x00000000, 0xffffff00, 0xffff0000, 0xff000000 - }; -#endif -#if BYTE_ORDER == LITTLE_ENDIAN - static const uint32_t mask[4] = { - 0x00000000, 0x00ffffff, 0x0000ffff, 0x000000ff - }; -#endif - //printf("Applying pad mask: %p to %p\n", (void*)mask[padded-len], - // *reinterpret_cast<void**>(data+padded-4)); - *reinterpret_cast<uint32_t*>(data+padded-4) &= mask[padded-len]; - } - - finishWrite(padded); - return data; - } - - status_t err = growData(padded); - if (err == NO_ERROR) goto restart_write; - return NULL; -} - -status_t Parcel::writeInt32(int32_t val) -{ - if ((mDataPos+sizeof(val)) <= mDataCapacity) { -restart_write: - *reinterpret_cast<int32_t*>(mData+mDataPos) = val; - return finishWrite(sizeof(val)); - } - - status_t err = growData(sizeof(val)); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::writeInt64(int64_t val) -{ - if ((mDataPos+sizeof(val)) <= mDataCapacity) { -restart_write: - *reinterpret_cast<int64_t*>(mData+mDataPos) = val; - return finishWrite(sizeof(val)); - } - - status_t err = growData(sizeof(val)); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::writeFloat(float val) -{ - if ((mDataPos+sizeof(val)) <= mDataCapacity) { -restart_write: - *reinterpret_cast<float*>(mData+mDataPos) = val; - return finishWrite(sizeof(val)); - } - - status_t err = growData(sizeof(val)); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::writeDouble(double val) -{ - if ((mDataPos+sizeof(val)) <= mDataCapacity) { -restart_write: - *reinterpret_cast<double*>(mData+mDataPos) = val; - return finishWrite(sizeof(val)); - } - - status_t err = growData(sizeof(val)); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::writeCString(const char* str) -{ - return write(str, strlen(str)+1); -} - -status_t Parcel::writeString8(const String8& str) -{ - status_t err = writeInt32(str.bytes()); - if (err == NO_ERROR) { - err = write(str.string(), str.bytes()+1); - } - return err; -} - -status_t Parcel::writeString16(const String16& str) -{ - return writeString16(str.string(), str.size()); -} - -status_t Parcel::writeString16(const char16_t* str, size_t len) -{ - if (str == NULL) return writeInt32(-1); - - status_t err = writeInt32(len); - if (err == NO_ERROR) { - len *= sizeof(char16_t); - uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char16_t)); - if (data) { - memcpy(data, str, len); - *reinterpret_cast<char16_t*>(data+len) = 0; - return NO_ERROR; - } - err = mError; - } - return err; -} - -status_t Parcel::writeStrongBinder(const sp<IBinder>& val) -{ - return flatten_binder(ProcessState::self(), val, this); -} - -status_t Parcel::writeWeakBinder(const wp<IBinder>& val) -{ - return flatten_binder(ProcessState::self(), val, this); -} - -status_t Parcel::writeNativeHandle(const native_handle& handle) -{ - if (handle.version != sizeof(native_handle)) - return BAD_TYPE; - - status_t err; - err = writeInt32(handle.numFds); - if (err != NO_ERROR) return err; - - err = writeInt32(handle.numInts); - if (err != NO_ERROR) return err; - - for (int i=0 ; err==NO_ERROR && i<handle.numFds ; i++) - err = writeDupFileDescriptor(handle.data[i]); - - if (err != NO_ERROR) { - LOGD("write native handle, write dup fd failed"); - return err; - } - - err = write(handle.data + handle.numFds, sizeof(int)*handle.numInts); - - return err; -} - -status_t Parcel::writeFileDescriptor(int fd) -{ - flat_binder_object obj; - obj.type = BINDER_TYPE_FD; - obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - obj.handle = fd; - obj.cookie = (void*)0; - return writeObject(obj, true); -} - -status_t Parcel::writeDupFileDescriptor(int fd) -{ - flat_binder_object obj; - obj.type = BINDER_TYPE_FD; - obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - obj.handle = dup(fd); - obj.cookie = (void*)1; - return writeObject(obj, true); -} - -status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData) -{ - const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity; - const bool enoughObjects = mObjectsSize < mObjectsCapacity; - if (enoughData && enoughObjects) { -restart_write: - *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val; - - // Need to write meta-data? - if (nullMetaData || val.binder != NULL) { - mObjects[mObjectsSize] = mDataPos; - acquire_object(ProcessState::self(), val, this); - mObjectsSize++; - } - - // remember if it's a file descriptor - if (val.type == BINDER_TYPE_FD) { - mHasFds = mFdsKnown = true; - } - - return finishWrite(sizeof(flat_binder_object)); - } - - if (!enoughData) { - const status_t err = growData(sizeof(val)); - if (err != NO_ERROR) return err; - } - if (!enoughObjects) { - size_t newSize = ((mObjectsSize+2)*3)/2; - size_t* objects = (size_t*)realloc(mObjects, newSize*sizeof(size_t)); - if (objects == NULL) return NO_MEMORY; - mObjects = objects; - mObjectsCapacity = newSize; - } - - goto restart_write; -} - - -void Parcel::remove(size_t start, size_t amt) -{ - LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!"); -} - -status_t Parcel::read(void* outData, size_t len) const -{ - if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) { - memcpy(outData, mData+mDataPos, len); - mDataPos += PAD_SIZE(len); - LOGV("read Setting data pos of %p to %d\n", this, mDataPos); - return NO_ERROR; - } - return NOT_ENOUGH_DATA; -} - -const void* Parcel::readInplace(size_t len) const -{ - if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += PAD_SIZE(len); - LOGV("readInplace Setting data pos of %p to %d\n", this, mDataPos); - return data; - } - return NULL; -} - -status_t Parcel::readInt32(int32_t *pArg) const -{ - if ((mDataPos+sizeof(int32_t)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(int32_t); - *pArg = *reinterpret_cast<const int32_t*>(data); - return NO_ERROR; - } else { - return NOT_ENOUGH_DATA; - } -} - -int32_t Parcel::readInt32() const -{ - if ((mDataPos+sizeof(int32_t)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(int32_t); - LOGV("readInt32 Setting data pos of %p to %d\n", this, mDataPos); - return *reinterpret_cast<const int32_t*>(data); - } - return 0; -} - - -status_t Parcel::readInt64(int64_t *pArg) const -{ - if ((mDataPos+sizeof(int64_t)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(int64_t); - *pArg = *reinterpret_cast<const int64_t*>(data); - LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos); - return NO_ERROR; - } else { - return NOT_ENOUGH_DATA; - } -} - - -int64_t Parcel::readInt64() const -{ - if ((mDataPos+sizeof(int64_t)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(int64_t); - LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos); - return *reinterpret_cast<const int64_t*>(data); - } - return 0; -} - -status_t Parcel::readFloat(float *pArg) const -{ - if ((mDataPos+sizeof(float)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(float); - LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos); - *pArg = *reinterpret_cast<const float*>(data); - return NO_ERROR; - } else { - return NOT_ENOUGH_DATA; - } -} - - -float Parcel::readFloat() const -{ - if ((mDataPos+sizeof(float)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(float); - LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos); - return *reinterpret_cast<const float*>(data); - } - return 0; -} - -status_t Parcel::readDouble(double *pArg) const -{ - if ((mDataPos+sizeof(double)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(double); - LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos); - *pArg = *reinterpret_cast<const double*>(data); - return NO_ERROR; - } else { - return NOT_ENOUGH_DATA; - } -} - - -double Parcel::readDouble() const -{ - if ((mDataPos+sizeof(double)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(double); - LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos); - return *reinterpret_cast<const double*>(data); - } - return 0; -} - - -const char* Parcel::readCString() const -{ - const size_t avail = mDataSize-mDataPos; - if (avail > 0) { - const char* str = reinterpret_cast<const char*>(mData+mDataPos); - // is the string's trailing NUL within the parcel's valid bounds? - const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail)); - if (eos) { - const size_t len = eos - str; - mDataPos += PAD_SIZE(len+1); - LOGV("readCString Setting data pos of %p to %d\n", this, mDataPos); - return str; - } - } - return NULL; -} - -String8 Parcel::readString8() const -{ - int32_t size = readInt32(); - // watch for potential int overflow adding 1 for trailing NUL - if (size > 0 && size < INT32_MAX) { - const char* str = (const char*)readInplace(size+1); - if (str) return String8(str, size); - } - return String8(); -} - -String16 Parcel::readString16() const -{ - size_t len; - const char16_t* str = readString16Inplace(&len); - if (str) return String16(str, len); - LOGE("Reading a NULL string not supported here."); - return String16(); -} - -const char16_t* Parcel::readString16Inplace(size_t* outLen) const -{ - int32_t size = readInt32(); - // watch for potential int overflow from size+1 - if (size >= 0 && size < INT32_MAX) { - *outLen = size; - const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t)); - if (str != NULL) { - return str; - } - } - *outLen = 0; - return NULL; -} - -sp<IBinder> Parcel::readStrongBinder() const -{ - sp<IBinder> val; - unflatten_binder(ProcessState::self(), *this, &val); - return val; -} - -wp<IBinder> Parcel::readWeakBinder() const -{ - wp<IBinder> val; - unflatten_binder(ProcessState::self(), *this, &val); - return val; -} - - -native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int), void* cookie) const -{ - int numFds, numInts; - status_t err; - err = readInt32(&numFds); - if (err != NO_ERROR) return 0; - err = readInt32(&numInts); - if (err != NO_ERROR) return 0; - - native_handle* h; - if (alloc == 0) { - size_t size = sizeof(native_handle) + sizeof(int)*(numFds + numInts); - h = (native_handle*)malloc(size); - h->version = sizeof(native_handle); - h->numFds = numFds; - h->numInts = numInts; - } else { - h = alloc(cookie, numFds, numInts); - if (h->version != sizeof(native_handle)) { - return 0; - } - } - - for (int i=0 ; err==NO_ERROR && i<numFds ; i++) { - h->data[i] = dup(readFileDescriptor()); - if (h->data[i] < 0) err = BAD_VALUE; - } - - err = read(h->data + numFds, sizeof(int)*numInts); - - if (err != NO_ERROR) { - if (alloc == 0) { - free(h); - } - h = 0; - } - return h; -} - - -int Parcel::readFileDescriptor() const -{ - const flat_binder_object* flat = readObject(true); - if (flat) { - switch (flat->type) { - case BINDER_TYPE_FD: - //LOGI("Returning file descriptor %ld from parcel %p\n", flat->handle, this); - return flat->handle; - } - } - return BAD_TYPE; -} - -const flat_binder_object* Parcel::readObject(bool nullMetaData) const -{ - const size_t DPOS = mDataPos; - if ((DPOS+sizeof(flat_binder_object)) <= mDataSize) { - const flat_binder_object* obj - = reinterpret_cast<const flat_binder_object*>(mData+DPOS); - mDataPos = DPOS + sizeof(flat_binder_object); - if (!nullMetaData && (obj->cookie == NULL && obj->binder == NULL)) { - // When transferring a NULL object, we don't write it into - // the object list, so we don't want to check for it when - // reading. - LOGV("readObject Setting data pos of %p to %d\n", this, mDataPos); - return obj; - } - - // Ensure that this object is valid... - size_t* const OBJS = mObjects; - const size_t N = mObjectsSize; - size_t opos = mNextObjectHint; - - if (N > 0) { - LOGV("Parcel %p looking for obj at %d, hint=%d\n", - this, DPOS, opos); - - // Start at the current hint position, looking for an object at - // the current data position. - if (opos < N) { - while (opos < (N-1) && OBJS[opos] < DPOS) { - opos++; - } - } else { - opos = N-1; - } - if (OBJS[opos] == DPOS) { - // Found it! - LOGV("Parcel found obj %d at index %d with forward search", - this, DPOS, opos); - mNextObjectHint = opos+1; - LOGV("readObject Setting data pos of %p to %d\n", this, mDataPos); - return obj; - } - - // Look backwards for it... - while (opos > 0 && OBJS[opos] > DPOS) { - opos--; - } - if (OBJS[opos] == DPOS) { - // Found it! - LOGV("Parcel found obj %d at index %d with backward search", - this, DPOS, opos); - mNextObjectHint = opos+1; - LOGV("readObject Setting data pos of %p to %d\n", this, mDataPos); - return obj; - } - } - LOGW("Attempt to read object from Parcel %p at offset %d that is not in the object list", - this, DPOS); - } - return NULL; -} - -void Parcel::closeFileDescriptors() -{ - size_t i = mObjectsSize; - if (i > 0) { - //LOGI("Closing file descriptors for %d objects...", mObjectsSize); - } - while (i > 0) { - i--; - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]); - if (flat->type == BINDER_TYPE_FD) { - //LOGI("Closing fd: %ld\n", flat->handle); - close(flat->handle); - } - } -} - -const uint8_t* Parcel::ipcData() const -{ - return mData; -} - -size_t Parcel::ipcDataSize() const -{ - return (mDataSize > mDataPos ? mDataSize : mDataPos); -} - -const size_t* Parcel::ipcObjects() const -{ - return mObjects; -} - -size_t Parcel::ipcObjectsCount() const -{ - return mObjectsSize; -} - -void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, - const size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie) -{ - freeDataNoInit(); - mError = NO_ERROR; - mData = const_cast<uint8_t*>(data); - mDataSize = mDataCapacity = dataSize; - //LOGI("setDataReference Setting data size of %p to %lu (pid=%d)\n", this, mDataSize, getpid()); - mDataPos = 0; - LOGV("setDataReference Setting data pos of %p to %d\n", this, mDataPos); - mObjects = const_cast<size_t*>(objects); - mObjectsSize = mObjectsCapacity = objectsCount; - mNextObjectHint = 0; - mOwner = relFunc; - mOwnerCookie = relCookie; - scanForFds(); -} - -void Parcel::print(TextOutput& to, uint32_t flags) const -{ - to << "Parcel("; - - if (errorCheck() != NO_ERROR) { - const status_t err = errorCheck(); - to << "Error: " << (void*)err << " \"" << strerror(-err) << "\""; - } else if (dataSize() > 0) { - const uint8_t* DATA = data(); - to << indent << HexDump(DATA, dataSize()) << dedent; - const size_t* OBJS = objects(); - const size_t N = objectsCount(); - for (size_t i=0; i<N; i++) { - const flat_binder_object* flat - = reinterpret_cast<const flat_binder_object*>(DATA+OBJS[i]); - to << endl << "Object #" << i << " @ " << (void*)OBJS[i] << ": " - << TypeCode(flat->type & 0x7f7f7f00) - << " = " << flat->binder; - } - } else { - to << "NULL"; - } - - to << ")"; -} - -void Parcel::releaseObjects() -{ - const sp<ProcessState> proc(ProcessState::self()); - size_t i = mObjectsSize; - uint8_t* const data = mData; - size_t* const objects = mObjects; - while (i > 0) { - i--; - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(data+objects[i]); - release_object(proc, *flat, this); - } -} - -void Parcel::acquireObjects() -{ - const sp<ProcessState> proc(ProcessState::self()); - size_t i = mObjectsSize; - uint8_t* const data = mData; - size_t* const objects = mObjects; - while (i > 0) { - i--; - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(data+objects[i]); - acquire_object(proc, *flat, this); - } -} - -void Parcel::freeData() -{ - freeDataNoInit(); - initState(); -} - -void Parcel::freeDataNoInit() -{ - if (mOwner) { - //LOGI("Freeing data ref of %p (pid=%d)\n", this, getpid()); - mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie); - } else { - releaseObjects(); - if (mData) free(mData); - if (mObjects) free(mObjects); - } -} - -status_t Parcel::growData(size_t len) -{ - size_t newSize = ((mDataSize+len)*3)/2; - return (newSize <= mDataSize) - ? (status_t) NO_MEMORY - : continueWrite(newSize); -} - -status_t Parcel::restartWrite(size_t desired) -{ - if (mOwner) { - freeData(); - return continueWrite(desired); - } - - uint8_t* data = (uint8_t*)realloc(mData, desired); - if (!data && desired > mDataCapacity) { - mError = NO_MEMORY; - return NO_MEMORY; - } - - releaseObjects(); - - if (data) { - mData = data; - mDataCapacity = desired; - } - - mDataSize = mDataPos = 0; - LOGV("restartWrite Setting data size of %p to %d\n", this, mDataSize); - LOGV("restartWrite Setting data pos of %p to %d\n", this, mDataPos); - - free(mObjects); - mObjects = NULL; - mObjectsSize = mObjectsCapacity = 0; - mNextObjectHint = 0; - mHasFds = false; - mFdsKnown = true; - - return NO_ERROR; -} - -status_t Parcel::continueWrite(size_t desired) -{ - // If shrinking, first adjust for any objects that appear - // after the new data size. - size_t objectsSize = mObjectsSize; - if (desired < mDataSize) { - if (desired == 0) { - objectsSize = 0; - } else { - while (objectsSize > 0) { - if (mObjects[objectsSize-1] < desired) - break; - objectsSize--; - } - } - } - - if (mOwner) { - // If the size is going to zero, just release the owner's data. - if (desired == 0) { - freeData(); - return NO_ERROR; - } - - // If there is a different owner, we need to take - // posession. - uint8_t* data = (uint8_t*)malloc(desired); - if (!data) { - mError = NO_MEMORY; - return NO_MEMORY; - } - size_t* objects = NULL; - - if (objectsSize) { - objects = (size_t*)malloc(objectsSize*sizeof(size_t)); - if (!objects) { - mError = NO_MEMORY; - return NO_MEMORY; - } - - // Little hack to only acquire references on objects - // we will be keeping. - size_t oldObjectsSize = mObjectsSize; - mObjectsSize = objectsSize; - acquireObjects(); - mObjectsSize = oldObjectsSize; - } - - if (mData) { - memcpy(data, mData, mDataSize < desired ? mDataSize : desired); - } - if (objects && mObjects) { - memcpy(objects, mObjects, objectsSize*sizeof(size_t)); - } - //LOGI("Freeing data ref of %p (pid=%d)\n", this, getpid()); - mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie); - mOwner = NULL; - - mData = data; - mObjects = objects; - mDataSize = (mDataSize < desired) ? mDataSize : desired; - LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); - mDataCapacity = desired; - mObjectsSize = mObjectsCapacity = objectsSize; - mNextObjectHint = 0; - - } else if (mData) { - if (objectsSize < mObjectsSize) { - // Need to release refs on any objects we are dropping. - const sp<ProcessState> proc(ProcessState::self()); - for (size_t i=objectsSize; i<mObjectsSize; i++) { - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]); - if (flat->type == BINDER_TYPE_FD) { - // will need to rescan because we may have lopped off the only FDs - mFdsKnown = false; - } - release_object(proc, *flat, this); - } - size_t* objects = - (size_t*)realloc(mObjects, objectsSize*sizeof(size_t)); - if (objects) { - mObjects = objects; - } - mObjectsSize = objectsSize; - mNextObjectHint = 0; - } - - // We own the data, so we can just do a realloc(). - if (desired > mDataCapacity) { - uint8_t* data = (uint8_t*)realloc(mData, desired); - if (data) { - mData = data; - mDataCapacity = desired; - } else if (desired > mDataCapacity) { - mError = NO_MEMORY; - return NO_MEMORY; - } - } else { - mDataSize = desired; - LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); - if (mDataPos > desired) { - mDataPos = desired; - LOGV("continueWrite Setting data pos of %p to %d\n", this, mDataPos); - } - } - - } else { - // This is the first data. Easy! - uint8_t* data = (uint8_t*)malloc(desired); - if (!data) { - mError = NO_MEMORY; - return NO_MEMORY; - } - - if(!(mDataCapacity == 0 && mObjects == NULL - && mObjectsCapacity == 0)) { - LOGE("continueWrite: %d/%p/%d/%d", mDataCapacity, mObjects, mObjectsCapacity, desired); - } - - mData = data; - mDataSize = mDataPos = 0; - LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); - LOGV("continueWrite Setting data pos of %p to %d\n", this, mDataPos); - mDataCapacity = desired; - } - - return NO_ERROR; -} - -void Parcel::initState() -{ - mError = NO_ERROR; - mData = 0; - mDataSize = 0; - mDataCapacity = 0; - mDataPos = 0; - LOGV("initState Setting data size of %p to %d\n", this, mDataSize); - LOGV("initState Setting data pos of %p to %d\n", this, mDataPos); - mObjects = NULL; - mObjectsSize = 0; - mObjectsCapacity = 0; - mNextObjectHint = 0; - mHasFds = false; - mFdsKnown = true; - mOwner = NULL; -} - -void Parcel::scanForFds() const -{ - bool hasFds = false; - for (size_t i=0; i<mObjectsSize; i++) { - const flat_binder_object* flat - = reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]); - if (flat->type == BINDER_TYPE_FD) { - hasFds = true; - break; - } - } - mHasFds = hasFds; - mFdsKnown = true; -} - -}; // namespace android diff --git a/libs/utils/Pipe.cpp b/libs/utils/Pipe.cpp deleted file mode 100644 index 613906b..0000000 --- a/libs/utils/Pipe.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Unidirectional pipe. -// - -#include <utils/Pipe.h> -#include <utils/Log.h> - -#if defined(HAVE_WIN32_IPC) -# include <windows.h> -#else -# include <fcntl.h> -# include <unistd.h> -# include <errno.h> -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <assert.h> -#include <string.h> - -using namespace android; - -const unsigned long kInvalidHandle = (unsigned long) -1; - - -/* - * Constructor. Do little. - */ -Pipe::Pipe(void) - : mReadNonBlocking(false), mReadHandle(kInvalidHandle), - mWriteHandle(kInvalidHandle) -{ -} - -/* - * Destructor. Use the system-appropriate close call. - */ -Pipe::~Pipe(void) -{ -#if defined(HAVE_WIN32_IPC) - if (mReadHandle != kInvalidHandle) { - if (!CloseHandle((HANDLE)mReadHandle)) - LOG(LOG_WARN, "pipe", "failed closing read handle (%ld)\n", - mReadHandle); - } - if (mWriteHandle != kInvalidHandle) { - FlushFileBuffers((HANDLE)mWriteHandle); - if (!CloseHandle((HANDLE)mWriteHandle)) - LOG(LOG_WARN, "pipe", "failed closing write handle (%ld)\n", - mWriteHandle); - } -#else - if (mReadHandle != kInvalidHandle) { - if (close((int) mReadHandle) != 0) - LOG(LOG_WARN, "pipe", "failed closing read fd (%d)\n", - (int) mReadHandle); - } - if (mWriteHandle != kInvalidHandle) { - if (close((int) mWriteHandle) != 0) - LOG(LOG_WARN, "pipe", "failed closing write fd (%d)\n", - (int) mWriteHandle); - } -#endif -} - -/* - * Create the pipe. - * - * Use the POSIX stuff for everything but Windows. - */ -bool Pipe::create(void) -{ - assert(mReadHandle == kInvalidHandle); - assert(mWriteHandle == kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - /* we use this across processes, so they need to be inheritable */ - HANDLE handles[2]; - SECURITY_ATTRIBUTES saAttr; - - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - if (!CreatePipe(&handles[0], &handles[1], &saAttr, 0)) { - LOG(LOG_ERROR, "pipe", "unable to create pipe\n"); - return false; - } - mReadHandle = (unsigned long) handles[0]; - mWriteHandle = (unsigned long) handles[1]; - return true; -#else - int fds[2]; - - if (pipe(fds) != 0) { - LOG(LOG_ERROR, "pipe", "unable to create pipe\n"); - return false; - } - mReadHandle = fds[0]; - mWriteHandle = fds[1]; - return true; -#endif -} - -/* - * Create a "half pipe". Please, no Segway riding. - */ -bool Pipe::createReader(unsigned long handle) -{ - mReadHandle = handle; - assert(mWriteHandle == kInvalidHandle); - return true; -} - -/* - * Create a "half pipe" for writing. - */ -bool Pipe::createWriter(unsigned long handle) -{ - mWriteHandle = handle; - assert(mReadHandle == kInvalidHandle); - return true; -} - -/* - * Return "true" if create() has been called successfully. - */ -bool Pipe::isCreated(void) -{ - // one or the other should be open - return (mReadHandle != kInvalidHandle || mWriteHandle != kInvalidHandle); -} - - -/* - * Read data from the pipe. - * - * For Linux and Darwin, just call read(). For Windows, implement - * non-blocking reads by calling PeekNamedPipe first. - */ -int Pipe::read(void* buf, int count) -{ - assert(mReadHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - DWORD totalBytesAvail = count; - DWORD bytesRead; - - if (mReadNonBlocking) { - // use PeekNamedPipe to adjust read count expectations - if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL, - &totalBytesAvail, NULL)) - { - LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n"); - return -1; - } - - if (totalBytesAvail == 0) - return 0; - } - - if (!ReadFile((HANDLE) mReadHandle, buf, totalBytesAvail, &bytesRead, - NULL)) - { - DWORD err = GetLastError(); - if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE) - return 0; - LOG(LOG_ERROR, "pipe", "ReadFile failed (err=%ld)\n", err); - return -1; - } - - return (int) bytesRead; -#else - int cc; - cc = ::read(mReadHandle, buf, count); - if (cc < 0 && errno == EAGAIN) - return 0; - return cc; -#endif -} - -/* - * Write data to the pipe. - * - * POSIX systems are trivial, Windows uses a different call and doesn't - * handle non-blocking writes. - * - * If we add non-blocking support here, we probably want to make it an - * all-or-nothing write. - * - * DO NOT use LOG() here, we could be writing a log message. - */ -int Pipe::write(const void* buf, int count) -{ - assert(mWriteHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - DWORD bytesWritten; - - if (mWriteNonBlocking) { - // BUG: can't use PeekNamedPipe() to get the amount of space - // left. Looks like we need to use "overlapped I/O" functions. - // I just don't care that much. - } - - if (!WriteFile((HANDLE) mWriteHandle, buf, count, &bytesWritten, NULL)) { - // can't LOG, use stderr - fprintf(stderr, "WriteFile failed (err=%ld)\n", GetLastError()); - return -1; - } - - return (int) bytesWritten; -#else - int cc; - cc = ::write(mWriteHandle, buf, count); - if (cc < 0 && errno == EAGAIN) - return 0; - return cc; -#endif -} - -/* - * Figure out if there is data available on the read fd. - * - * We return "true" on error because we want the caller to try to read - * from the pipe. They'll notice the read failure and do something - * appropriate. - */ -bool Pipe::readReady(void) -{ - assert(mReadHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - DWORD totalBytesAvail; - - if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL, - &totalBytesAvail, NULL)) - { - LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n"); - return true; - } - - return (totalBytesAvail != 0); -#else - errno = 0; - fd_set readfds; - struct timeval tv = { 0, 0 }; - int cc; - - FD_ZERO(&readfds); - FD_SET(mReadHandle, &readfds); - - cc = select(mReadHandle+1, &readfds, NULL, NULL, &tv); - if (cc < 0) { - LOG(LOG_ERROR, "pipe", "select() failed\n"); - return true; - } else if (cc == 0) { - /* timed out, nothing available */ - return false; - } else if (cc == 1) { - /* our fd is ready */ - return true; - } else { - LOG(LOG_ERROR, "pipe", "HUH? select() returned > 1\n"); - return true; - } -#endif -} - -/* - * Enable or disable non-blocking mode for the read descriptor. - * - * NOTE: the calls succeed under Mac OS X, but the pipe doesn't appear to - * actually be in non-blocking mode. If this matters -- i.e. you're not - * using a select() call -- put a call to readReady() in front of the - * ::read() call, with a PIPE_NONBLOCK_BROKEN #ifdef in the Makefile for - * Darwin. - */ -bool Pipe::setReadNonBlocking(bool val) -{ - assert(mReadHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - // nothing to do -#else - int flags; - - if (fcntl(mReadHandle, F_GETFL, &flags) == -1) { - LOG(LOG_ERROR, "pipe", "couldn't get flags for pipe read fd\n"); - return false; - } - if (val) - flags |= O_NONBLOCK; - else - flags &= ~(O_NONBLOCK); - if (fcntl(mReadHandle, F_SETFL, &flags) == -1) { - LOG(LOG_ERROR, "pipe", "couldn't set flags for pipe read fd\n"); - return false; - } -#endif - - mReadNonBlocking = val; - return true; -} - -/* - * Enable or disable non-blocking mode for the write descriptor. - * - * As with setReadNonBlocking(), this does not work on the Mac. - */ -bool Pipe::setWriteNonBlocking(bool val) -{ - assert(mWriteHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - // nothing to do -#else - int flags; - - if (fcntl(mWriteHandle, F_GETFL, &flags) == -1) { - LOG(LOG_WARN, "pipe", - "Warning: couldn't get flags for pipe write fd (errno=%d)\n", - errno); - return false; - } - if (val) - flags |= O_NONBLOCK; - else - flags &= ~(O_NONBLOCK); - if (fcntl(mWriteHandle, F_SETFL, &flags) == -1) { - LOG(LOG_WARN, "pipe", - "Warning: couldn't set flags for pipe write fd (errno=%d)\n", - errno); - return false; - } -#endif - - mWriteNonBlocking = val; - return true; -} - -/* - * Specify whether a file descriptor can be inherited by a child process. - * Under Linux this means setting the close-on-exec flag, under Windows - * this is SetHandleInformation(HANDLE_FLAG_INHERIT). - */ -bool Pipe::disallowReadInherit(void) -{ - if (mReadHandle == kInvalidHandle) - return false; - -#if defined(HAVE_WIN32_IPC) - if (SetHandleInformation((HANDLE) mReadHandle, HANDLE_FLAG_INHERIT, 0) == 0) - return false; -#else - if (fcntl((int) mReadHandle, F_SETFD, FD_CLOEXEC) != 0) - return false; -#endif - return true; -} -bool Pipe::disallowWriteInherit(void) -{ - if (mWriteHandle == kInvalidHandle) - return false; - -#if defined(HAVE_WIN32_IPC) - if (SetHandleInformation((HANDLE) mWriteHandle, HANDLE_FLAG_INHERIT, 0) == 0) - return false; -#else - if (fcntl((int) mWriteHandle, F_SETFD, FD_CLOEXEC) != 0) - return false; -#endif - return true; -} - -/* - * Close read descriptor. - */ -bool Pipe::closeRead(void) -{ - if (mReadHandle == kInvalidHandle) - return false; - -#if defined(HAVE_WIN32_IPC) - if (mReadHandle != kInvalidHandle) { - if (!CloseHandle((HANDLE)mReadHandle)) { - LOG(LOG_WARN, "pipe", "failed closing read handle\n"); - return false; - } - } -#else - if (mReadHandle != kInvalidHandle) { - if (close((int) mReadHandle) != 0) { - LOG(LOG_WARN, "pipe", "failed closing read fd\n"); - return false; - } - } -#endif - mReadHandle = kInvalidHandle; - return true; -} - -/* - * Close write descriptor. - */ -bool Pipe::closeWrite(void) -{ - if (mWriteHandle == kInvalidHandle) - return false; - -#if defined(HAVE_WIN32_IPC) - if (mWriteHandle != kInvalidHandle) { - if (!CloseHandle((HANDLE)mWriteHandle)) { - LOG(LOG_WARN, "pipe", "failed closing write handle\n"); - return false; - } - } -#else - if (mWriteHandle != kInvalidHandle) { - if (close((int) mWriteHandle) != 0) { - LOG(LOG_WARN, "pipe", "failed closing write fd\n"); - return false; - } - } -#endif - mWriteHandle = kInvalidHandle; - return true; -} - -/* - * Get the read handle. - */ -unsigned long Pipe::getReadHandle(void) -{ - assert(mReadHandle != kInvalidHandle); - - return mReadHandle; -} - -/* - * Get the write handle. - */ -unsigned long Pipe::getWriteHandle(void) -{ - assert(mWriteHandle != kInvalidHandle); - - return mWriteHandle; -} - diff --git a/libs/utils/ProcessState.cpp b/libs/utils/ProcessState.cpp deleted file mode 100644 index 4567df6..0000000 --- a/libs/utils/ProcessState.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "ProcessState" - -#include <cutils/process_name.h> - -#include <utils/ProcessState.h> - -#include <utils/Atomic.h> -#include <utils/BpBinder.h> -#include <utils/IPCThreadState.h> -#include <utils/Log.h> -#include <utils/String8.h> -#include <utils/IServiceManager.h> -#include <utils/String8.h> -#include <utils/threads.h> - -#include <private/utils/binder_module.h> -#include <private/utils/Static.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/stat.h> - -#define BINDER_VM_SIZE (1*1024*1024) - -static bool gSingleProcess = false; - - -// --------------------------------------------------------------------------- - -namespace android { - -// Global variables -int mArgC; -const char* const* mArgV; -int mArgLen; - -class PoolThread : public Thread -{ -public: - PoolThread(bool isMain) - : mIsMain(isMain) - { - } - -protected: - virtual bool threadLoop() - { - IPCThreadState::self()->joinThreadPool(mIsMain); - return false; - } - - const bool mIsMain; -}; - -sp<ProcessState> ProcessState::self() -{ - if (gProcess != NULL) return gProcess; - - AutoMutex _l(gProcessMutex); - if (gProcess == NULL) gProcess = new ProcessState; - return gProcess; -} - -void ProcessState::setSingleProcess(bool singleProcess) -{ - gSingleProcess = singleProcess; -} - - -void ProcessState::setContextObject(const sp<IBinder>& object) -{ - setContextObject(object, String16("default")); -} - -sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) -{ - if (supportsProcesses()) { - return getStrongProxyForHandle(0); - } else { - return getContextObject(String16("default"), caller); - } -} - -void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name) -{ - AutoMutex _l(mLock); - mContexts.add(name, object); -} - -sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinder>& caller) -{ - mLock.lock(); - sp<IBinder> object( - mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : NULL); - mLock.unlock(); - - //printf("Getting context object %s for %p\n", String8(name).string(), caller.get()); - - if (object != NULL) return object; - - // Don't attempt to retrieve contexts if we manage them - if (mManagesContexts) { - LOGE("getContextObject(%s) failed, but we manage the contexts!\n", - String8(name).string()); - return NULL; - } - - IPCThreadState* ipc = IPCThreadState::self(); - { - Parcel data, reply; - // no interface token on this magic transaction - data.writeString16(name); - data.writeStrongBinder(caller); - status_t result = ipc->transact(0 /*magic*/, 0, data, &reply, 0); - if (result == NO_ERROR) { - object = reply.readStrongBinder(); - } - } - - ipc->flushCommands(); - - if (object != NULL) setContextObject(object, name); - return object; -} - -bool ProcessState::supportsProcesses() const -{ - return mDriverFD >= 0; -} - -void ProcessState::startThreadPool() -{ - AutoMutex _l(mLock); - if (!mThreadPoolStarted) { - mThreadPoolStarted = true; - spawnPooledThread(true); - } -} - -bool ProcessState::isContextManager(void) const -{ - return mManagesContexts; -} - -bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData) -{ - if (!mManagesContexts) { - AutoMutex _l(mLock); - mBinderContextCheckFunc = checkFunc; - mBinderContextUserData = userData; - if (mDriverFD >= 0) { - int dummy = 0; -#if defined(HAVE_ANDROID_OS) - status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy); -#else - status_t result = INVALID_OPERATION; -#endif - if (result == 0) { - mManagesContexts = true; - } else if (result == -1) { - mBinderContextCheckFunc = NULL; - mBinderContextUserData = NULL; - LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno)); - } - } else { - // If there is no driver, our only world is the local - // process so we can always become the context manager there. - mManagesContexts = true; - } - } - return mManagesContexts; -} - -ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle) -{ - const size_t N=mHandleToObject.size(); - if (N <= (size_t)handle) { - handle_entry e; - e.binder = NULL; - e.refs = NULL; - status_t err = mHandleToObject.insertAt(e, N, handle+1-N); - if (err < NO_ERROR) return NULL; - } - return &mHandleToObject.editItemAt(handle); -} - -sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) -{ - sp<IBinder> result; - - AutoMutex _l(mLock); - - handle_entry* e = lookupHandleLocked(handle); - - if (e != NULL) { - // We need to create a new BpBinder if there isn't currently one, OR we - // are unable to acquire a weak reference on this current one. See comment - // in getWeakProxyForHandle() for more info about this. - IBinder* b = e->binder; - if (b == NULL || !e->refs->attemptIncWeak(this)) { - b = new BpBinder(handle); - e->binder = b; - if (b) e->refs = b->getWeakRefs(); - result = b; - } else { - // This little bit of nastyness is to allow us to add a primary - // reference to the remote proxy when this team doesn't have one - // but another team is sending the handle to us. - result.force_set(b); - e->refs->decWeak(this); - } - } - - return result; -} - -wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle) -{ - wp<IBinder> result; - - AutoMutex _l(mLock); - - handle_entry* e = lookupHandleLocked(handle); - - if (e != NULL) { - // We need to create a new BpBinder if there isn't currently one, OR we - // are unable to acquire a weak reference on this current one. The - // attemptIncWeak() is safe because we know the BpBinder destructor will always - // call expungeHandle(), which acquires the same lock we are holding now. - // We need to do this because there is a race condition between someone - // releasing a reference on this BpBinder, and a new reference on its handle - // arriving from the driver. - IBinder* b = e->binder; - if (b == NULL || !e->refs->attemptIncWeak(this)) { - b = new BpBinder(handle); - result = b; - e->binder = b; - if (b) e->refs = b->getWeakRefs(); - } else { - result = b; - e->refs->decWeak(this); - } - } - - return result; -} - -void ProcessState::expungeHandle(int32_t handle, IBinder* binder) -{ - AutoMutex _l(mLock); - - handle_entry* e = lookupHandleLocked(handle); - - // This handle may have already been replaced with a new BpBinder - // (if someone failed the AttemptIncWeak() above); we don't want - // to overwrite it. - if (e && e->binder == binder) e->binder = NULL; -} - -void ProcessState::setArgs(int argc, const char* const argv[]) -{ - mArgC = argc; - mArgV = (const char **)argv; - - mArgLen = 0; - for (int i=0; i<argc; i++) { - mArgLen += strlen(argv[i]) + 1; - } - mArgLen--; -} - -int ProcessState::getArgC() const -{ - return mArgC; -} - -const char* const* ProcessState::getArgV() const -{ - return mArgV; -} - -void ProcessState::setArgV0(const char* txt) -{ - if (mArgV != NULL) { - strncpy((char*)mArgV[0], txt, mArgLen); - set_process_name(txt); - } -} - -void ProcessState::spawnPooledThread(bool isMain) -{ - if (mThreadPoolStarted) { - int32_t s = android_atomic_add(1, &mThreadPoolSeq); - char buf[32]; - sprintf(buf, "Binder Thread #%d", s); - LOGV("Spawning new pooled thread, name=%s\n", buf); - sp<Thread> t = new PoolThread(isMain); - t->run(buf); - } -} - -static int open_driver() -{ - if (gSingleProcess) { - return -1; - } - - int fd = open("/dev/binder", O_RDWR); - if (fd >= 0) { - fcntl(fd, F_SETFD, FD_CLOEXEC); - int vers; -#if defined(HAVE_ANDROID_OS) - status_t result = ioctl(fd, BINDER_VERSION, &vers); -#else - status_t result = -1; - errno = EPERM; -#endif - if (result == -1) { - LOGE("Binder ioctl to obtain version failed: %s", strerror(errno)); - close(fd); - fd = -1; - } - if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) { - LOGE("Binder driver protocol does not match user space protocol!"); - close(fd); - fd = -1; - } -#if defined(HAVE_ANDROID_OS) - size_t maxThreads = 15; - result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); - if (result == -1) { - LOGE("Binder ioctl to set max threads failed: %s", strerror(errno)); - } -#endif - - } else { - LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno)); - } - return fd; -} - -ProcessState::ProcessState() - : mDriverFD(open_driver()) - , mVMStart(MAP_FAILED) - , mManagesContexts(false) - , mBinderContextCheckFunc(NULL) - , mBinderContextUserData(NULL) - , mThreadPoolStarted(false) - , mThreadPoolSeq(1) -{ - if (mDriverFD >= 0) { - // XXX Ideally, there should be a specific define for whether we - // have mmap (or whether we could possibly have the kernel module - // availabla). -#if !defined(HAVE_WIN32_IPC) - // mmap the binder, providing a chunk of virtual address space to receive transactions. - mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); - if (mVMStart == MAP_FAILED) { - // *sigh* - LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n"); - close(mDriverFD); - mDriverFD = -1; - } -#else - mDriverFD = -1; -#endif - } - if (mDriverFD < 0) { - // Need to run without the driver, starting our own thread pool. - } -} - -ProcessState::~ProcessState() -{ -} - -}; // namespace android diff --git a/libs/utils/README b/libs/utils/README deleted file mode 100644 index 36a706d..0000000 --- a/libs/utils/README +++ /dev/null @@ -1,14 +0,0 @@ -Android Utility Function Library - -If you need a feature that is native to Linux but not present on other -platforms, construct a platform-dependent implementation that shares -the Linux interface. That way the actual device runs as "light" as -possible. - -If that isn't feasible, create a system-independent interface and hide -the details. - -The ultimate goal is *not* to create a super-duper platform abstraction -layer. The goal is to provide an optimized solution for Linux with -reasonable implementations for other platforms. - diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp deleted file mode 100644 index 0bd1af4..0000000 --- a/libs/utils/RefBase.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "RefBase" - -#include <utils/RefBase.h> - -#include <utils/Atomic.h> -#include <utils/CallStack.h> -#include <utils/KeyedVector.h> -#include <utils/Log.h> -#include <utils/threads.h> - -#include <stdlib.h> -#include <stdio.h> -#include <typeinfo> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> - -// compile with refcounting debugging enabled -#define DEBUG_REFS 0 -#define DEBUG_REFS_ENABLED_BY_DEFAULT 1 -#define DEBUG_REFS_CALLSTACK_ENABLED 1 - -// log all reference counting operations -#define PRINT_REFS 0 - -// --------------------------------------------------------------------------- - -namespace android { - -#define INITIAL_STRONG_VALUE (1<<28) - -// --------------------------------------------------------------------------- - -class RefBase::weakref_impl : public RefBase::weakref_type -{ -public: - volatile int32_t mStrong; - volatile int32_t mWeak; - RefBase* const mBase; - volatile int32_t mFlags; - - -#if !DEBUG_REFS - - weakref_impl(RefBase* base) - : mStrong(INITIAL_STRONG_VALUE) - , mWeak(0) - , mBase(base) - , mFlags(0) - { - } - - void addStrongRef(const void* /*id*/) { } - void removeStrongRef(const void* /*id*/) { } - void addWeakRef(const void* /*id*/) { } - void removeWeakRef(const void* /*id*/) { } - void printRefs() const { } - void trackMe(bool, bool) { } - -#else - - weakref_impl(RefBase* base) - : mStrong(INITIAL_STRONG_VALUE) - , mWeak(0) - , mBase(base) - , mFlags(0) - , mStrongRefs(NULL) - , mWeakRefs(NULL) - , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT) - , mRetain(false) - { - //LOGI("NEW weakref_impl %p for RefBase %p", this, base); - } - - ~weakref_impl() - { - LOG_ALWAYS_FATAL_IF(!mRetain && mStrongRefs != NULL, "Strong references remain!"); - LOG_ALWAYS_FATAL_IF(!mRetain && mWeakRefs != NULL, "Weak references remain!"); - } - - void addStrongRef(const void* id) - { - addRef(&mStrongRefs, id, mStrong); - } - - void removeStrongRef(const void* id) - { - if (!mRetain) - removeRef(&mStrongRefs, id); - else - addRef(&mStrongRefs, id, -mStrong); - } - - void addWeakRef(const void* id) - { - addRef(&mWeakRefs, id, mWeak); - } - - void removeWeakRef(const void* id) - { - if (!mRetain) - removeRef(&mWeakRefs, id); - else - addRef(&mWeakRefs, id, -mWeak); - } - - void trackMe(bool track, bool retain) - { - mTrackEnabled = track; - mRetain = retain; - } - - void printRefs() const - { - String8 text; - - { - AutoMutex _l(const_cast<weakref_impl*>(this)->mMutex); - - char buf[128]; - sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this); - text.append(buf); - printRefsLocked(&text, mStrongRefs); - sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this); - text.append(buf); - printRefsLocked(&text, mWeakRefs); - } - - { - char name[100]; - snprintf(name, 100, "/data/%p.stack", this); - int rc = open(name, O_RDWR | O_CREAT | O_APPEND); - if (rc >= 0) { - write(rc, text.string(), text.length()); - close(rc); - LOGD("STACK TRACE for %p saved in %s", this, name); - } - else LOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this, - name, strerror(errno)); - } - } - -private: - struct ref_entry - { - ref_entry* next; - const void* id; -#if DEBUG_REFS_CALLSTACK_ENABLED - CallStack stack; -#endif - int32_t ref; - }; - - void addRef(ref_entry** refs, const void* id, int32_t mRef) - { - if (mTrackEnabled) { - AutoMutex _l(mMutex); - ref_entry* ref = new ref_entry; - // Reference count at the time of the snapshot, but before the - // update. Positive value means we increment, negative--we - // decrement the reference count. - ref->ref = mRef; - ref->id = id; -#if DEBUG_REFS_CALLSTACK_ENABLED - ref->stack.update(2); -#endif - - ref->next = *refs; - *refs = ref; - } - } - - void removeRef(ref_entry** refs, const void* id) - { - if (mTrackEnabled) { - AutoMutex _l(mMutex); - - ref_entry* ref = *refs; - while (ref != NULL) { - if (ref->id == id) { - *refs = ref->next; - delete ref; - return; - } - - refs = &ref->next; - ref = *refs; - } - - LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p (weakref_type %p) that doesn't exist!", - id, mBase, this); - } - } - - void printRefsLocked(String8* out, const ref_entry* refs) const - { - char buf[128]; - while (refs) { - char inc = refs->ref >= 0 ? '+' : '-'; - sprintf(buf, "\t%c ID %p (ref %d):\n", - inc, refs->id, refs->ref); - out->append(buf); -#if DEBUG_REFS_CALLSTACK_ENABLED - out->append(refs->stack.toString("\t\t")); -#else - out->append("\t\t(call stacks disabled)"); -#endif - refs = refs->next; - } - } - - Mutex mMutex; - ref_entry* mStrongRefs; - ref_entry* mWeakRefs; - - bool mTrackEnabled; - // Collect stack traces on addref and removeref, instead of deleting the stack references - // on removeref that match the address ones. - bool mRetain; - -#if 0 - void addRef(KeyedVector<const void*, int32_t>* refs, const void* id) - { - AutoMutex _l(mMutex); - ssize_t i = refs->indexOfKey(id); - if (i >= 0) { - ++(refs->editValueAt(i)); - } else { - i = refs->add(id, 1); - } - } - - void removeRef(KeyedVector<const void*, int32_t>* refs, const void* id) - { - AutoMutex _l(mMutex); - ssize_t i = refs->indexOfKey(id); - LOG_ALWAYS_FATAL_IF(i < 0, "RefBase: removing id %p that doesn't exist!", id); - if (i >= 0) { - int32_t val = --(refs->editValueAt(i)); - if (val == 0) { - refs->removeItemsAt(i); - } - } - } - - void printRefs(const KeyedVector<const void*, int32_t>& refs) - { - const size_t N=refs.size(); - for (size_t i=0; i<N; i++) { - printf("\tID %p: %d remain\n", refs.keyAt(i), refs.valueAt(i)); - } - } - - mutable Mutex mMutex; - KeyedVector<const void*, int32_t> mStrongRefs; - KeyedVector<const void*, int32_t> mWeakRefs; -#endif - -#endif -}; - -// --------------------------------------------------------------------------- - -void RefBase::incStrong(const void* id) const -{ - weakref_impl* const refs = mRefs; - refs->addWeakRef(id); - refs->incWeak(id); - - refs->addStrongRef(id); - const int32_t c = android_atomic_inc(&refs->mStrong); - LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs); -#if PRINT_REFS - LOGD("incStrong of %p from %p: cnt=%d\n", this, id, c); -#endif - if (c != INITIAL_STRONG_VALUE) { - return; - } - - android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); - const_cast<RefBase*>(this)->onFirstRef(); -} - -void RefBase::decStrong(const void* id) const -{ - weakref_impl* const refs = mRefs; - refs->removeStrongRef(id); - const int32_t c = android_atomic_dec(&refs->mStrong); -#if PRINT_REFS - LOGD("decStrong of %p from %p: cnt=%d\n", this, id, c); -#endif - LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs); - if (c == 1) { - const_cast<RefBase*>(this)->onLastStrongRef(id); - if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) { - delete this; - } - } - refs->removeWeakRef(id); - refs->decWeak(id); -} - -void RefBase::forceIncStrong(const void* id) const -{ - weakref_impl* const refs = mRefs; - refs->addWeakRef(id); - refs->incWeak(id); - - refs->addStrongRef(id); - const int32_t c = android_atomic_inc(&refs->mStrong); - LOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow", - refs); -#if PRINT_REFS - LOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c); -#endif - - switch (c) { - case INITIAL_STRONG_VALUE: - android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); - // fall through... - case 0: - const_cast<RefBase*>(this)->onFirstRef(); - } -} - -int32_t RefBase::getStrongCount() const -{ - return mRefs->mStrong; -} - - - -RefBase* RefBase::weakref_type::refBase() const -{ - return static_cast<const weakref_impl*>(this)->mBase; -} - -void RefBase::weakref_type::incWeak(const void* id) -{ - weakref_impl* const impl = static_cast<weakref_impl*>(this); - impl->addWeakRef(id); - const int32_t c = android_atomic_inc(&impl->mWeak); - LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this); -} - -void RefBase::weakref_type::decWeak(const void* id) -{ - weakref_impl* const impl = static_cast<weakref_impl*>(this); - impl->removeWeakRef(id); - const int32_t c = android_atomic_dec(&impl->mWeak); - LOG_ASSERT(c >= 1, "decWeak called on %p too many times", this); - if (c != 1) return; - - if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) { - if (impl->mStrong == INITIAL_STRONG_VALUE) - delete impl->mBase; - else { -// LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase); - delete impl; - } - } else { - impl->mBase->onLastWeakRef(id); - if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) { - delete impl->mBase; - } - } -} - -bool RefBase::weakref_type::attemptIncStrong(const void* id) -{ - incWeak(id); - - weakref_impl* const impl = static_cast<weakref_impl*>(this); - - int32_t curCount = impl->mStrong; - LOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow", - this); - while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) { - if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) { - break; - } - curCount = impl->mStrong; - } - - if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) { - bool allow; - if (curCount == INITIAL_STRONG_VALUE) { - // Attempting to acquire first strong reference... this is allowed - // if the object does NOT have a longer lifetime (meaning the - // implementation doesn't need to see this), or if the implementation - // allows it to happen. - allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK - || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); - } else { - // Attempting to revive the object... this is allowed - // if the object DOES have a longer lifetime (so we can safely - // call the object with only a weak ref) and the implementation - // allows it to happen. - allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK - && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); - } - if (!allow) { - decWeak(id); - return false; - } - curCount = android_atomic_inc(&impl->mStrong); - - // If the strong reference count has already been incremented by - // someone else, the implementor of onIncStrongAttempted() is holding - // an unneeded reference. So call onLastStrongRef() here to remove it. - // (No, this is not pretty.) Note that we MUST NOT do this if we - // are in fact acquiring the first reference. - if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) { - impl->mBase->onLastStrongRef(id); - } - } - - impl->addWeakRef(id); - impl->addStrongRef(id); - -#if PRINT_REFS - LOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount); -#endif - - if (curCount == INITIAL_STRONG_VALUE) { - android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong); - impl->mBase->onFirstRef(); - } - - return true; -} - -bool RefBase::weakref_type::attemptIncWeak(const void* id) -{ - weakref_impl* const impl = static_cast<weakref_impl*>(this); - - int32_t curCount = impl->mWeak; - LOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow", - this); - while (curCount > 0) { - if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) { - break; - } - curCount = impl->mWeak; - } - - if (curCount > 0) { - impl->addWeakRef(id); - } - - return curCount > 0; -} - -int32_t RefBase::weakref_type::getWeakCount() const -{ - return static_cast<const weakref_impl*>(this)->mWeak; -} - -void RefBase::weakref_type::printRefs() const -{ - static_cast<const weakref_impl*>(this)->printRefs(); -} - -void RefBase::weakref_type::trackMe(bool enable, bool retain) -{ - static_cast<const weakref_impl*>(this)->trackMe(enable, retain); -} - -RefBase::weakref_type* RefBase::createWeak(const void* id) const -{ - mRefs->incWeak(id); - return mRefs; -} - -RefBase::weakref_type* RefBase::getWeakRefs() const -{ - return mRefs; -} - -RefBase::RefBase() - : mRefs(new weakref_impl(this)) -{ -// LOGV("Creating refs %p with RefBase %p\n", mRefs, this); -} - -RefBase::~RefBase() -{ -// LOGV("Destroying RefBase %p (refs %p)\n", this, mRefs); - if (mRefs->mWeak == 0) { -// LOGV("Freeing refs %p of old RefBase %p\n", mRefs, this); - delete mRefs; - } -} - -void RefBase::extendObjectLifetime(int32_t mode) -{ - android_atomic_or(mode, &mRefs->mFlags); -} - -void RefBase::onFirstRef() -{ -} - -void RefBase::onLastStrongRef(const void* /*id*/) -{ -} - -bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id) -{ - return (flags&FIRST_INC_STRONG) ? true : false; -} - -void RefBase::onLastWeakRef(const void* /*id*/) -{ -} - -}; // namespace android diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp deleted file mode 100644 index 71e7cd7..0000000 --- a/libs/utils/ResourceTypes.cpp +++ /dev/null @@ -1,3983 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "ResourceType" -//#define LOG_NDEBUG 0 - -#include <utils/Atomic.h> -#include <utils/ByteOrder.h> -#include <utils/Debug.h> -#include <utils/ResourceTypes.h> -#include <utils/String16.h> -#include <utils/String8.h> -#include <utils/TextOutput.h> -#include <utils/Log.h> - -#include <stdlib.h> -#include <string.h> -#include <memory.h> -#include <ctype.h> -#include <stdint.h> - -#ifndef INT32_MAX -#define INT32_MAX ((int32_t)(2147483647)) -#endif - -#define POOL_NOISY(x) //x -#define XML_NOISY(x) //x -#define TABLE_NOISY(x) //x -#define TABLE_GETENTRY(x) //x -#define TABLE_SUPER_NOISY(x) //x -#define LOAD_TABLE_NOISY(x) //x - -namespace android { - -#ifdef HAVE_WINSOCK -#undef nhtol -#undef htonl - -#ifdef HAVE_LITTLE_ENDIAN -#define ntohl(x) ( ((x) << 24) | (((x) >> 24) & 255) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) ) -#define htonl(x) ntohl(x) -#define ntohs(x) ( (((x) << 8) & 0xff00) | (((x) >> 8) & 255) ) -#define htons(x) ntohs(x) -#else -#define ntohl(x) (x) -#define htonl(x) (x) -#define ntohs(x) (x) -#define htons(x) (x) -#endif -#endif - -static void printToLogFunc(void* cookie, const char* txt) -{ - LOGV("%s", txt); -} - -// Standard C isspace() is only required to look at the low byte of its input, so -// produces incorrect results for UTF-16 characters. For safety's sake, assume that -// any high-byte UTF-16 code point is not whitespace. -inline int isspace16(char16_t c) { - return (c < 0x0080 && isspace(c)); -} - -// range checked; guaranteed to NUL-terminate within the stated number of available slots -// NOTE: if this truncates the dst string due to running out of space, no attempt is -// made to avoid splitting surrogate pairs. -static void strcpy16_dtoh(uint16_t* dst, const uint16_t* src, size_t avail) -{ - uint16_t* last = dst + avail - 1; - while (*src && (dst < last)) { - char16_t s = dtohs(*src); - *dst++ = s; - src++; - } - *dst = 0; -} - -static status_t validate_chunk(const ResChunk_header* chunk, - size_t minSize, - const uint8_t* dataEnd, - const char* name) -{ - const uint16_t headerSize = dtohs(chunk->headerSize); - const uint32_t size = dtohl(chunk->size); - - if (headerSize >= minSize) { - if (headerSize <= size) { - if (((headerSize|size)&0x3) == 0) { - if ((ssize_t)size <= (dataEnd-((const uint8_t*)chunk))) { - return NO_ERROR; - } - LOGW("%s data size %p extends beyond resource end %p.", - name, (void*)size, - (void*)(dataEnd-((const uint8_t*)chunk))); - return BAD_TYPE; - } - LOGW("%s size 0x%x or headerSize 0x%x is not on an integer boundary.", - name, (int)size, (int)headerSize); - return BAD_TYPE; - } - LOGW("%s size %p is smaller than header size %p.", - name, (void*)size, (void*)(int)headerSize); - return BAD_TYPE; - } - LOGW("%s header size %p is too small.", - name, (void*)(int)headerSize); - return BAD_TYPE; -} - -inline void Res_value::copyFrom_dtoh(const Res_value& src) -{ - size = dtohs(src.size); - res0 = src.res0; - dataType = src.dataType; - data = dtohl(src.data); -} - -void Res_png_9patch::deviceToFile() -{ - for (int i = 0; i < numXDivs; i++) { - xDivs[i] = htonl(xDivs[i]); - } - for (int i = 0; i < numYDivs; i++) { - yDivs[i] = htonl(yDivs[i]); - } - paddingLeft = htonl(paddingLeft); - paddingRight = htonl(paddingRight); - paddingTop = htonl(paddingTop); - paddingBottom = htonl(paddingBottom); - for (int i=0; i<numColors; i++) { - colors[i] = htonl(colors[i]); - } -} - -void Res_png_9patch::fileToDevice() -{ - for (int i = 0; i < numXDivs; i++) { - xDivs[i] = ntohl(xDivs[i]); - } - for (int i = 0; i < numYDivs; i++) { - yDivs[i] = ntohl(yDivs[i]); - } - paddingLeft = ntohl(paddingLeft); - paddingRight = ntohl(paddingRight); - paddingTop = ntohl(paddingTop); - paddingBottom = ntohl(paddingBottom); - for (int i=0; i<numColors; i++) { - colors[i] = ntohl(colors[i]); - } -} - -size_t Res_png_9patch::serializedSize() -{ - // The size of this struct is 32 bytes on the 32-bit target system - // 4 * int8_t - // 4 * int32_t - // 3 * pointer - return 32 - + numXDivs * sizeof(int32_t) - + numYDivs * sizeof(int32_t) - + numColors * sizeof(uint32_t); -} - -void* Res_png_9patch::serialize() -{ - void* newData = malloc(serializedSize()); - serialize(newData); - return newData; -} - -void Res_png_9patch::serialize(void * outData) -{ - char* data = (char*) outData; - memmove(data, &wasDeserialized, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors - memmove(data + 12, &paddingLeft, 16); // copy paddingXXXX - data += 32; - - memmove(data, this->xDivs, numXDivs * sizeof(int32_t)); - data += numXDivs * sizeof(int32_t); - memmove(data, this->yDivs, numYDivs * sizeof(int32_t)); - data += numYDivs * sizeof(int32_t); - memmove(data, this->colors, numColors * sizeof(uint32_t)); -} - -static void deserializeInternal(const void* inData, Res_png_9patch* outData) { - char* patch = (char*) inData; - if (inData != outData) { - memmove(&outData->wasDeserialized, patch, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors - memmove(&outData->paddingLeft, patch + 12, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors - } - outData->wasDeserialized = true; - char* data = (char*)outData; - data += sizeof(Res_png_9patch); - outData->xDivs = (int32_t*) data; - data += outData->numXDivs * sizeof(int32_t); - outData->yDivs = (int32_t*) data; - data += outData->numYDivs * sizeof(int32_t); - outData->colors = (uint32_t*) data; -} - -Res_png_9patch* Res_png_9patch::deserialize(const void* inData) -{ - if (sizeof(void*) != sizeof(int32_t)) { - LOGE("Cannot deserialize on non 32-bit system\n"); - return NULL; - } - deserializeInternal(inData, (Res_png_9patch*) inData); - return (Res_png_9patch*) inData; -} - -// -------------------------------------------------------------------- -// -------------------------------------------------------------------- -// -------------------------------------------------------------------- - -ResStringPool::ResStringPool() - : mError(NO_INIT), mOwnedData(NULL) -{ -} - -ResStringPool::ResStringPool(const void* data, size_t size, bool copyData) - : mError(NO_INIT), mOwnedData(NULL) -{ - setTo(data, size, copyData); -} - -ResStringPool::~ResStringPool() -{ - uninit(); -} - -status_t ResStringPool::setTo(const void* data, size_t size, bool copyData) -{ - if (!data || !size) { - return (mError=BAD_TYPE); - } - - uninit(); - - const bool notDeviceEndian = htods(0xf0) != 0xf0; - - if (copyData || notDeviceEndian) { - mOwnedData = malloc(size); - if (mOwnedData == NULL) { - return (mError=NO_MEMORY); - } - memcpy(mOwnedData, data, size); - data = mOwnedData; - } - - mHeader = (const ResStringPool_header*)data; - - if (notDeviceEndian) { - ResStringPool_header* h = const_cast<ResStringPool_header*>(mHeader); - h->header.headerSize = dtohs(mHeader->header.headerSize); - h->header.type = dtohs(mHeader->header.type); - h->header.size = dtohl(mHeader->header.size); - h->stringCount = dtohl(mHeader->stringCount); - h->styleCount = dtohl(mHeader->styleCount); - h->flags = dtohl(mHeader->flags); - h->stringsStart = dtohl(mHeader->stringsStart); - h->stylesStart = dtohl(mHeader->stylesStart); - } - - if (mHeader->header.headerSize > mHeader->header.size - || mHeader->header.size > size) { - LOGW("Bad string block: header size %d or total size %d is larger than data size %d\n", - (int)mHeader->header.headerSize, (int)mHeader->header.size, (int)size); - return (mError=BAD_TYPE); - } - mSize = mHeader->header.size; - mEntries = (const uint32_t*) - (((const uint8_t*)data)+mHeader->header.headerSize); - - if (mHeader->stringCount > 0) { - if ((mHeader->stringCount*sizeof(uint32_t) < mHeader->stringCount) // uint32 overflow? - || (mHeader->header.headerSize+(mHeader->stringCount*sizeof(uint32_t))) - > size) { - LOGW("Bad string block: entry of %d items extends past data size %d\n", - (int)(mHeader->header.headerSize+(mHeader->stringCount*sizeof(uint32_t))), - (int)size); - return (mError=BAD_TYPE); - } - mStrings = (const char16_t*) - (((const uint8_t*)data)+mHeader->stringsStart); - if (mHeader->stringsStart >= (mHeader->header.size-sizeof(uint16_t))) { - LOGW("Bad string block: string pool starts at %d, after total size %d\n", - (int)mHeader->stringsStart, (int)mHeader->header.size); - return (mError=BAD_TYPE); - } - if (mHeader->styleCount == 0) { - mStringPoolSize = - (mHeader->header.size-mHeader->stringsStart)/sizeof(uint16_t); - } else { - // check invariant: styles follow the strings - if (mHeader->stylesStart <= mHeader->stringsStart) { - LOGW("Bad style block: style block starts at %d, before strings at %d\n", - (int)mHeader->stylesStart, (int)mHeader->stringsStart); - return (mError=BAD_TYPE); - } - mStringPoolSize = - (mHeader->stylesStart-mHeader->stringsStart)/sizeof(uint16_t); - } - - // check invariant: stringCount > 0 requires a string pool to exist - if (mStringPoolSize == 0) { - LOGW("Bad string block: stringCount is %d but pool size is 0\n", (int)mHeader->stringCount); - return (mError=BAD_TYPE); - } - - if (notDeviceEndian) { - size_t i; - uint32_t* e = const_cast<uint32_t*>(mEntries); - for (i=0; i<mHeader->stringCount; i++) { - e[i] = dtohl(mEntries[i]); - } - char16_t* s = const_cast<char16_t*>(mStrings); - for (i=0; i<mStringPoolSize; i++) { - s[i] = dtohs(mStrings[i]); - } - } - - if (mStrings[mStringPoolSize-1] != 0) { - LOGW("Bad string block: last string is not 0-terminated\n"); - return (mError=BAD_TYPE); - } - } else { - mStrings = NULL; - mStringPoolSize = 0; - } - - if (mHeader->styleCount > 0) { - mEntryStyles = mEntries + mHeader->stringCount; - // invariant: integer overflow in calculating mEntryStyles - if (mEntryStyles < mEntries) { - LOGW("Bad string block: integer overflow finding styles\n"); - return (mError=BAD_TYPE); - } - - if (((const uint8_t*)mEntryStyles-(const uint8_t*)mHeader) > (int)size) { - LOGW("Bad string block: entry of %d styles extends past data size %d\n", - (int)((const uint8_t*)mEntryStyles-(const uint8_t*)mHeader), - (int)size); - return (mError=BAD_TYPE); - } - mStyles = (const uint32_t*) - (((const uint8_t*)data)+mHeader->stylesStart); - if (mHeader->stylesStart >= mHeader->header.size) { - LOGW("Bad string block: style pool starts %d, after total size %d\n", - (int)mHeader->stylesStart, (int)mHeader->header.size); - return (mError=BAD_TYPE); - } - mStylePoolSize = - (mHeader->header.size-mHeader->stylesStart)/sizeof(uint32_t); - - if (notDeviceEndian) { - size_t i; - uint32_t* e = const_cast<uint32_t*>(mEntryStyles); - for (i=0; i<mHeader->styleCount; i++) { - e[i] = dtohl(mEntryStyles[i]); - } - uint32_t* s = const_cast<uint32_t*>(mStyles); - for (i=0; i<mStylePoolSize; i++) { - s[i] = dtohl(mStyles[i]); - } - } - - const ResStringPool_span endSpan = { - { htodl(ResStringPool_span::END) }, - htodl(ResStringPool_span::END), htodl(ResStringPool_span::END) - }; - if (memcmp(&mStyles[mStylePoolSize-(sizeof(endSpan)/sizeof(uint32_t))], - &endSpan, sizeof(endSpan)) != 0) { - LOGW("Bad string block: last style is not 0xFFFFFFFF-terminated\n"); - return (mError=BAD_TYPE); - } - } else { - mEntryStyles = NULL; - mStyles = NULL; - mStylePoolSize = 0; - } - - return (mError=NO_ERROR); -} - -status_t ResStringPool::getError() const -{ - return mError; -} - -void ResStringPool::uninit() -{ - mError = NO_INIT; - if (mOwnedData) { - free(mOwnedData); - mOwnedData = NULL; - } -} - -const uint16_t* ResStringPool::stringAt(size_t idx, size_t* outLen) const -{ - if (mError == NO_ERROR && idx < mHeader->stringCount) { - const uint32_t off = (mEntries[idx]/sizeof(uint16_t)); - if (off < (mStringPoolSize-1)) { - const char16_t* str = mStrings+off; - *outLen = *str; - if ((*str)&0x8000) { - str++; - *outLen = (((*outLen)&0x7fff)<<16) + *str; - } - if ((uint32_t)(str+1+*outLen-mStrings) < mStringPoolSize) { - return str+1; - } else { - LOGW("Bad string block: string #%d extends to %d, past end at %d\n", - (int)idx, (int)(str+1+*outLen-mStrings), (int)mStringPoolSize); - } - } else { - LOGW("Bad string block: string #%d entry is at %d, past end at %d\n", - (int)idx, (int)(off*sizeof(uint16_t)), - (int)(mStringPoolSize*sizeof(uint16_t))); - } - } - return NULL; -} - -const ResStringPool_span* ResStringPool::styleAt(const ResStringPool_ref& ref) const -{ - return styleAt(ref.index); -} - -const ResStringPool_span* ResStringPool::styleAt(size_t idx) const -{ - if (mError == NO_ERROR && idx < mHeader->styleCount) { - const uint32_t off = (mEntryStyles[idx]/sizeof(uint32_t)); - if (off < mStylePoolSize) { - return (const ResStringPool_span*)(mStyles+off); - } else { - LOGW("Bad string block: style #%d entry is at %d, past end at %d\n", - (int)idx, (int)(off*sizeof(uint32_t)), - (int)(mStylePoolSize*sizeof(uint32_t))); - } - } - return NULL; -} - -ssize_t ResStringPool::indexOfString(const char16_t* str, size_t strLen) const -{ - if (mError != NO_ERROR) { - return mError; - } - - size_t len; - - if (mHeader->flags&ResStringPool_header::SORTED_FLAG) { - // Do a binary search for the string... - ssize_t l = 0; - ssize_t h = mHeader->stringCount-1; - - ssize_t mid; - while (l <= h) { - mid = l + (h - l)/2; - const char16_t* s = stringAt(mid, &len); - int c = s ? strzcmp16(s, len, str, strLen) : -1; - POOL_NOISY(printf("Looking for %s, at %s, cmp=%d, l/mid/h=%d/%d/%d\n", - String8(str).string(), - String8(s).string(), - c, (int)l, (int)mid, (int)h)); - if (c == 0) { - return mid; - } else if (c < 0) { - l = mid + 1; - } else { - h = mid - 1; - } - } - } else { - // It is unusual to get the ID from an unsorted string block... - // most often this happens because we want to get IDs for style - // span tags; since those always appear at the end of the string - // block, start searching at the back. - for (int i=mHeader->stringCount-1; i>=0; i--) { - const char16_t* s = stringAt(i, &len); - POOL_NOISY(printf("Looking for %s, at %s, i=%d\n", - String8(str, strLen).string(), - String8(s).string(), - i)); - if (s && strzcmp16(s, len, str, strLen) == 0) { - return i; - } - } - } - - return NAME_NOT_FOUND; -} - -size_t ResStringPool::size() const -{ - return (mError == NO_ERROR) ? mHeader->stringCount : 0; -} - -// -------------------------------------------------------------------- -// -------------------------------------------------------------------- -// -------------------------------------------------------------------- - -ResXMLParser::ResXMLParser(const ResXMLTree& tree) - : mTree(tree), mEventCode(BAD_DOCUMENT) -{ -} - -void ResXMLParser::restart() -{ - mCurNode = NULL; - mEventCode = mTree.mError == NO_ERROR ? START_DOCUMENT : BAD_DOCUMENT; -} - -ResXMLParser::event_code_t ResXMLParser::getEventType() const -{ - return mEventCode; -} - -ResXMLParser::event_code_t ResXMLParser::next() -{ - if (mEventCode == START_DOCUMENT) { - mCurNode = mTree.mRootNode; - mCurExt = mTree.mRootExt; - return (mEventCode=mTree.mRootCode); - } else if (mEventCode >= FIRST_CHUNK_CODE) { - return nextNode(); - } - return mEventCode; -} - -const int32_t ResXMLParser::getCommentID() const -{ - return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1; -} - -const uint16_t* ResXMLParser::getComment(size_t* outLen) const -{ - int32_t id = getCommentID(); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -const uint32_t ResXMLParser::getLineNumber() const -{ - return mCurNode != NULL ? dtohl(mCurNode->lineNumber) : -1; -} - -const int32_t ResXMLParser::getTextID() const -{ - if (mEventCode == TEXT) { - return dtohl(((const ResXMLTree_cdataExt*)mCurExt)->data.index); - } - return -1; -} - -const uint16_t* ResXMLParser::getText(size_t* outLen) const -{ - int32_t id = getTextID(); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -ssize_t ResXMLParser::getTextValue(Res_value* outValue) const -{ - if (mEventCode == TEXT) { - outValue->copyFrom_dtoh(((const ResXMLTree_cdataExt*)mCurExt)->typedData); - return sizeof(Res_value); - } - return BAD_TYPE; -} - -const int32_t ResXMLParser::getNamespacePrefixID() const -{ - if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) { - return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->prefix.index); - } - return -1; -} - -const uint16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const -{ - int32_t id = getNamespacePrefixID(); - //printf("prefix=%d event=%p\n", id, mEventCode); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -const int32_t ResXMLParser::getNamespaceUriID() const -{ - if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) { - return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->uri.index); - } - return -1; -} - -const uint16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const -{ - int32_t id = getNamespaceUriID(); - //printf("uri=%d event=%p\n", id, mEventCode); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -const int32_t ResXMLParser::getElementNamespaceID() const -{ - if (mEventCode == START_TAG) { - return dtohl(((const ResXMLTree_attrExt*)mCurExt)->ns.index); - } - if (mEventCode == END_TAG) { - return dtohl(((const ResXMLTree_endElementExt*)mCurExt)->ns.index); - } - return -1; -} - -const uint16_t* ResXMLParser::getElementNamespace(size_t* outLen) const -{ - int32_t id = getElementNamespaceID(); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -const int32_t ResXMLParser::getElementNameID() const -{ - if (mEventCode == START_TAG) { - return dtohl(((const ResXMLTree_attrExt*)mCurExt)->name.index); - } - if (mEventCode == END_TAG) { - return dtohl(((const ResXMLTree_endElementExt*)mCurExt)->name.index); - } - return -1; -} - -const uint16_t* ResXMLParser::getElementName(size_t* outLen) const -{ - int32_t id = getElementNameID(); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -size_t ResXMLParser::getAttributeCount() const -{ - if (mEventCode == START_TAG) { - return dtohs(((const ResXMLTree_attrExt*)mCurExt)->attributeCount); - } - return 0; -} - -const int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const -{ - if (mEventCode == START_TAG) { - const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt; - if (idx < dtohs(tag->attributeCount)) { - const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*) - (((const uint8_t*)tag) - + dtohs(tag->attributeStart) - + (dtohs(tag->attributeSize)*idx)); - return dtohl(attr->ns.index); - } - } - return -2; -} - -const uint16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const -{ - int32_t id = getAttributeNamespaceID(idx); - //printf("attribute namespace=%d idx=%d event=%p\n", id, idx, mEventCode); - //XML_NOISY(printf("getAttributeNamespace 0x%x=0x%x\n", idx, id)); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -const int32_t ResXMLParser::getAttributeNameID(size_t idx) const -{ - if (mEventCode == START_TAG) { - const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt; - if (idx < dtohs(tag->attributeCount)) { - const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*) - (((const uint8_t*)tag) - + dtohs(tag->attributeStart) - + (dtohs(tag->attributeSize)*idx)); - return dtohl(attr->name.index); - } - } - return -1; -} - -const uint16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const -{ - int32_t id = getAttributeNameID(idx); - //printf("attribute name=%d idx=%d event=%p\n", id, idx, mEventCode); - //XML_NOISY(printf("getAttributeName 0x%x=0x%x\n", idx, id)); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -const uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const -{ - int32_t id = getAttributeNameID(idx); - if (id >= 0 && (size_t)id < mTree.mNumResIds) { - return dtohl(mTree.mResIds[id]); - } - return 0; -} - -const int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const -{ - if (mEventCode == START_TAG) { - const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt; - if (idx < dtohs(tag->attributeCount)) { - const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*) - (((const uint8_t*)tag) - + dtohs(tag->attributeStart) - + (dtohs(tag->attributeSize)*idx)); - return dtohl(attr->rawValue.index); - } - } - return -1; -} - -const uint16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const -{ - int32_t id = getAttributeValueStringID(idx); - //XML_NOISY(printf("getAttributeValue 0x%x=0x%x\n", idx, id)); - return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; -} - -int32_t ResXMLParser::getAttributeDataType(size_t idx) const -{ - if (mEventCode == START_TAG) { - const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt; - if (idx < dtohs(tag->attributeCount)) { - const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*) - (((const uint8_t*)tag) - + dtohs(tag->attributeStart) - + (dtohs(tag->attributeSize)*idx)); - return attr->typedValue.dataType; - } - } - return Res_value::TYPE_NULL; -} - -int32_t ResXMLParser::getAttributeData(size_t idx) const -{ - if (mEventCode == START_TAG) { - const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt; - if (idx < dtohs(tag->attributeCount)) { - const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*) - (((const uint8_t*)tag) - + dtohs(tag->attributeStart) - + (dtohs(tag->attributeSize)*idx)); - return dtohl(attr->typedValue.data); - } - } - return 0; -} - -ssize_t ResXMLParser::getAttributeValue(size_t idx, Res_value* outValue) const -{ - if (mEventCode == START_TAG) { - const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt; - if (idx < dtohs(tag->attributeCount)) { - const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*) - (((const uint8_t*)tag) - + dtohs(tag->attributeStart) - + (dtohs(tag->attributeSize)*idx)); - outValue->copyFrom_dtoh(attr->typedValue); - return sizeof(Res_value); - } - } - return BAD_TYPE; -} - -ssize_t ResXMLParser::indexOfAttribute(const char* ns, const char* attr) const -{ - String16 nsStr(ns != NULL ? ns : ""); - String16 attrStr(attr); - return indexOfAttribute(ns ? nsStr.string() : NULL, ns ? nsStr.size() : 0, - attrStr.string(), attrStr.size()); -} - -ssize_t ResXMLParser::indexOfAttribute(const char16_t* ns, size_t nsLen, - const char16_t* attr, size_t attrLen) const -{ - if (mEventCode == START_TAG) { - const size_t N = getAttributeCount(); - for (size_t i=0; i<N; i++) { - size_t curNsLen, curAttrLen; - const char16_t* curNs = getAttributeNamespace(i, &curNsLen); - const char16_t* curAttr = getAttributeName(i, &curAttrLen); - //printf("%d: ns=%p attr=%p curNs=%p curAttr=%p\n", - // i, ns, attr, curNs, curAttr); - //printf(" --> attr=%s, curAttr=%s\n", - // String8(attr).string(), String8(curAttr).string()); - if (attr && curAttr && (strzcmp16(attr, attrLen, curAttr, curAttrLen) == 0)) { - if (ns == NULL) { - if (curNs == NULL) return i; - } else if (curNs != NULL) { - //printf(" --> ns=%s, curNs=%s\n", - // String8(ns).string(), String8(curNs).string()); - if (strzcmp16(ns, nsLen, curNs, curNsLen) == 0) return i; - } - } - } - } - - return NAME_NOT_FOUND; -} - -ssize_t ResXMLParser::indexOfID() const -{ - if (mEventCode == START_TAG) { - const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->idIndex); - if (idx > 0) return (idx-1); - } - return NAME_NOT_FOUND; -} - -ssize_t ResXMLParser::indexOfClass() const -{ - if (mEventCode == START_TAG) { - const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->classIndex); - if (idx > 0) return (idx-1); - } - return NAME_NOT_FOUND; -} - -ssize_t ResXMLParser::indexOfStyle() const -{ - if (mEventCode == START_TAG) { - const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->styleIndex); - if (idx > 0) return (idx-1); - } - return NAME_NOT_FOUND; -} - -ResXMLParser::event_code_t ResXMLParser::nextNode() -{ - if (mEventCode < 0) { - return mEventCode; - } - - do { - const ResXMLTree_node* next = (const ResXMLTree_node*) - (((const uint8_t*)mCurNode) + dtohl(mCurNode->header.size)); - //LOGW("Next node: prev=%p, next=%p\n", mCurNode, next); - - if (((const uint8_t*)next) >= mTree.mDataEnd) { - mCurNode = NULL; - return (mEventCode=END_DOCUMENT); - } - - if (mTree.validateNode(next) != NO_ERROR) { - mCurNode = NULL; - return (mEventCode=BAD_DOCUMENT); - } - - mCurNode = next; - const uint16_t headerSize = dtohs(next->header.headerSize); - const uint32_t totalSize = dtohl(next->header.size); - mCurExt = ((const uint8_t*)next) + headerSize; - size_t minExtSize = 0; - event_code_t eventCode = (event_code_t)dtohs(next->header.type); - switch ((mEventCode=eventCode)) { - case RES_XML_START_NAMESPACE_TYPE: - case RES_XML_END_NAMESPACE_TYPE: - minExtSize = sizeof(ResXMLTree_namespaceExt); - break; - case RES_XML_START_ELEMENT_TYPE: - minExtSize = sizeof(ResXMLTree_attrExt); - break; - case RES_XML_END_ELEMENT_TYPE: - minExtSize = sizeof(ResXMLTree_endElementExt); - break; - case RES_XML_CDATA_TYPE: - minExtSize = sizeof(ResXMLTree_cdataExt); - break; - default: - LOGW("Unknown XML block: header type %d in node at %d\n", - (int)dtohs(next->header.type), - (int)(((const uint8_t*)next)-((const uint8_t*)mTree.mHeader))); - continue; - } - - if ((totalSize-headerSize) < minExtSize) { - LOGW("Bad XML block: header type 0x%x in node at 0x%x has size %d, need %d\n", - (int)dtohs(next->header.type), - (int)(((const uint8_t*)next)-((const uint8_t*)mTree.mHeader)), - (int)(totalSize-headerSize), (int)minExtSize); - return (mEventCode=BAD_DOCUMENT); - } - - //printf("CurNode=%p, CurExt=%p, headerSize=%d, minExtSize=%d\n", - // mCurNode, mCurExt, headerSize, minExtSize); - - return eventCode; - } while (true); -} - -void ResXMLParser::getPosition(ResXMLParser::ResXMLPosition* pos) const -{ - pos->eventCode = mEventCode; - pos->curNode = mCurNode; - pos->curExt = mCurExt; -} - -void ResXMLParser::setPosition(const ResXMLParser::ResXMLPosition& pos) -{ - mEventCode = pos.eventCode; - mCurNode = pos.curNode; - mCurExt = pos.curExt; -} - - -// -------------------------------------------------------------------- - -static volatile int32_t gCount = 0; - -ResXMLTree::ResXMLTree() - : ResXMLParser(*this) - , mError(NO_INIT), mOwnedData(NULL) -{ - //LOGI("Creating ResXMLTree %p #%d\n", this, android_atomic_inc(&gCount)+1); - restart(); -} - -ResXMLTree::ResXMLTree(const void* data, size_t size, bool copyData) - : ResXMLParser(*this) - , mError(NO_INIT), mOwnedData(NULL) -{ - //LOGI("Creating ResXMLTree %p #%d\n", this, android_atomic_inc(&gCount)+1); - setTo(data, size, copyData); -} - -ResXMLTree::~ResXMLTree() -{ - //LOGI("Destroying ResXMLTree in %p #%d\n", this, android_atomic_dec(&gCount)-1); - uninit(); -} - -status_t ResXMLTree::setTo(const void* data, size_t size, bool copyData) -{ - uninit(); - mEventCode = START_DOCUMENT; - - if (copyData) { - mOwnedData = malloc(size); - if (mOwnedData == NULL) { - return (mError=NO_MEMORY); - } - memcpy(mOwnedData, data, size); - data = mOwnedData; - } - - mHeader = (const ResXMLTree_header*)data; - mSize = dtohl(mHeader->header.size); - if (dtohs(mHeader->header.headerSize) > mSize || mSize > size) { - LOGW("Bad XML block: header size %d or total size %d is larger than data size %d\n", - (int)dtohs(mHeader->header.headerSize), - (int)dtohl(mHeader->header.size), (int)size); - mError = BAD_TYPE; - restart(); - return mError; - } - mDataEnd = ((const uint8_t*)mHeader) + mSize; - - mStrings.uninit(); - mRootNode = NULL; - mResIds = NULL; - mNumResIds = 0; - - // First look for a couple interesting chunks: the string block - // and first XML node. - const ResChunk_header* chunk = - (const ResChunk_header*)(((const uint8_t*)mHeader) + dtohs(mHeader->header.headerSize)); - const ResChunk_header* lastChunk = chunk; - while (((const uint8_t*)chunk) < (mDataEnd-sizeof(ResChunk_header)) && - ((const uint8_t*)chunk) < (mDataEnd-dtohl(chunk->size))) { - status_t err = validate_chunk(chunk, sizeof(ResChunk_header), mDataEnd, "XML"); - if (err != NO_ERROR) { - mError = err; - goto done; - } - const uint16_t type = dtohs(chunk->type); - const size_t size = dtohl(chunk->size); - XML_NOISY(printf("Scanning @ %p: type=0x%x, size=0x%x\n", - (void*)(((uint32_t)chunk)-((uint32_t)mHeader)), type, size)); - if (type == RES_STRING_POOL_TYPE) { - mStrings.setTo(chunk, size); - } else if (type == RES_XML_RESOURCE_MAP_TYPE) { - mResIds = (const uint32_t*) - (((const uint8_t*)chunk)+dtohs(chunk->headerSize)); - mNumResIds = (dtohl(chunk->size)-dtohs(chunk->headerSize))/sizeof(uint32_t); - } else if (type >= RES_XML_FIRST_CHUNK_TYPE - && type <= RES_XML_LAST_CHUNK_TYPE) { - if (validateNode((const ResXMLTree_node*)chunk) != NO_ERROR) { - mError = BAD_TYPE; - goto done; - } - mCurNode = (const ResXMLTree_node*)lastChunk; - if (nextNode() == BAD_DOCUMENT) { - mError = BAD_TYPE; - goto done; - } - mRootNode = mCurNode; - mRootExt = mCurExt; - mRootCode = mEventCode; - break; - } else { - XML_NOISY(printf("Skipping unknown chunk!\n")); - } - lastChunk = chunk; - chunk = (const ResChunk_header*) - (((const uint8_t*)chunk) + size); - } - - if (mRootNode == NULL) { - LOGW("Bad XML block: no root element node found\n"); - mError = BAD_TYPE; - goto done; - } - - mError = mStrings.getError(); - -done: - restart(); - return mError; -} - -status_t ResXMLTree::getError() const -{ - return mError; -} - -void ResXMLTree::uninit() -{ - mError = NO_INIT; - if (mOwnedData) { - free(mOwnedData); - mOwnedData = NULL; - } - restart(); -} - -const ResStringPool& ResXMLTree::getStrings() const -{ - return mStrings; -} - -status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const -{ - const uint16_t eventCode = dtohs(node->header.type); - - status_t err = validate_chunk( - &node->header, sizeof(ResXMLTree_node), - mDataEnd, "ResXMLTree_node"); - - if (err >= NO_ERROR) { - // Only perform additional validation on START nodes - if (eventCode != RES_XML_START_ELEMENT_TYPE) { - return NO_ERROR; - } - - const uint16_t headerSize = dtohs(node->header.headerSize); - const uint32_t size = dtohl(node->header.size); - const ResXMLTree_attrExt* attrExt = (const ResXMLTree_attrExt*) - (((const uint8_t*)node) + headerSize); - // check for sensical values pulled out of the stream so far... - if ((size >= headerSize + sizeof(ResXMLTree_attrExt)) - && ((void*)attrExt > (void*)node)) { - const size_t attrSize = ((size_t)dtohs(attrExt->attributeSize)) - * dtohs(attrExt->attributeCount); - if ((dtohs(attrExt->attributeStart)+attrSize) <= (size-headerSize)) { - return NO_ERROR; - } - LOGW("Bad XML block: node attributes use 0x%x bytes, only have 0x%x bytes\n", - (unsigned int)(dtohs(attrExt->attributeStart)+attrSize), - (unsigned int)(size-headerSize)); - } - else { - LOGW("Bad XML start block: node header size 0x%x, size 0x%x\n", - (unsigned int)headerSize, (unsigned int)size); - } - return BAD_TYPE; - } - - return err; - -#if 0 - const bool isStart = dtohs(node->header.type) == RES_XML_START_ELEMENT_TYPE; - - const uint16_t headerSize = dtohs(node->header.headerSize); - const uint32_t size = dtohl(node->header.size); - - if (headerSize >= (isStart ? sizeof(ResXMLTree_attrNode) : sizeof(ResXMLTree_node))) { - if (size >= headerSize) { - if (((const uint8_t*)node) <= (mDataEnd-size)) { - if (!isStart) { - return NO_ERROR; - } - if ((((size_t)dtohs(node->attributeSize))*dtohs(node->attributeCount)) - <= (size-headerSize)) { - return NO_ERROR; - } - LOGW("Bad XML block: node attributes use 0x%x bytes, only have 0x%x bytes\n", - ((int)dtohs(node->attributeSize))*dtohs(node->attributeCount), - (int)(size-headerSize)); - return BAD_TYPE; - } - LOGW("Bad XML block: node at 0x%x extends beyond data end 0x%x\n", - (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)), (int)mSize); - return BAD_TYPE; - } - LOGW("Bad XML block: node at 0x%x header size 0x%x smaller than total size 0x%x\n", - (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)), - (int)headerSize, (int)size); - return BAD_TYPE; - } - LOGW("Bad XML block: node at 0x%x header size 0x%x too small\n", - (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)), - (int)headerSize); - return BAD_TYPE; -#endif -} - -// -------------------------------------------------------------------- -// -------------------------------------------------------------------- -// -------------------------------------------------------------------- - -struct ResTable::Header -{ - Header() : ownedData(NULL), header(NULL) { } - - void* ownedData; - const ResTable_header* header; - size_t size; - const uint8_t* dataEnd; - size_t index; - void* cookie; - - ResStringPool values; -}; - -struct ResTable::Type -{ - Type(const Header* _header, const Package* _package, size_t count) - : header(_header), package(_package), entryCount(count), - typeSpec(NULL), typeSpecFlags(NULL) { } - const Header* const header; - const Package* const package; - const size_t entryCount; - const ResTable_typeSpec* typeSpec; - const uint32_t* typeSpecFlags; - Vector<const ResTable_type*> configs; -}; - -struct ResTable::Package -{ - Package(const Header* _header, const ResTable_package* _package) - : header(_header), package(_package) { } - ~Package() - { - size_t i = types.size(); - while (i > 0) { - i--; - delete types[i]; - } - } - - const Header* const header; - const ResTable_package* const package; - Vector<Type*> types; - - const Type* getType(size_t idx) const { - return idx < types.size() ? types[idx] : NULL; - } -}; - -// A group of objects describing a particular resource package. -// The first in 'package' is always the root object (from the resource -// table that defined the package); the ones after are skins on top of it. -struct ResTable::PackageGroup -{ - PackageGroup(const String16& _name, uint32_t _id) - : name(_name), id(_id), typeCount(0), bags(NULL) { } - ~PackageGroup() { - clearBagCache(); - const size_t N = packages.size(); - for (size_t i=0; i<N; i++) { - delete packages[i]; - } - } - - void clearBagCache() { - if (bags) { - TABLE_NOISY(printf("bags=%p\n", bags)); - Package* pkg = packages[0]; - TABLE_NOISY(printf("typeCount=%x\n", typeCount)); - for (size_t i=0; i<typeCount; i++) { - TABLE_NOISY(printf("type=%d\n", i)); - const Type* type = pkg->getType(i); - if (type != NULL) { - bag_set** typeBags = bags[i]; - TABLE_NOISY(printf("typeBags=%p\n", typeBags)); - if (typeBags) { - TABLE_NOISY(printf("type->entryCount=%x\n", type->entryCount)); - const size_t N = type->entryCount; - for (size_t j=0; j<N; j++) { - if (typeBags[j] && typeBags[j] != (bag_set*)0xFFFFFFFF) - free(typeBags[j]); - } - free(typeBags); - } - } - } - free(bags); - bags = NULL; - } - } - - String16 const name; - uint32_t const id; - Vector<Package*> packages; - - // Taken from the root package. - ResStringPool typeStrings; - ResStringPool keyStrings; - size_t typeCount; - - // Computed attribute bags, first indexed by the type and second - // by the entry in that type. - bag_set*** bags; -}; - -struct ResTable::bag_set -{ - size_t numAttrs; // number in array - size_t availAttrs; // total space in array - uint32_t typeSpecFlags; - // Followed by 'numAttr' bag_entry structures. -}; - -ResTable::Theme::Theme(const ResTable& table) - : mTable(table) -{ - memset(mPackages, 0, sizeof(mPackages)); -} - -ResTable::Theme::~Theme() -{ - for (size_t i=0; i<Res_MAXPACKAGE; i++) { - package_info* pi = mPackages[i]; - if (pi != NULL) { - free_package(pi); - } - } -} - -void ResTable::Theme::free_package(package_info* pi) -{ - for (size_t j=0; j<pi->numTypes; j++) { - theme_entry* te = pi->types[j].entries; - if (te != NULL) { - free(te); - } - } - free(pi); -} - -ResTable::Theme::package_info* ResTable::Theme::copy_package(package_info* pi) -{ - package_info* newpi = (package_info*)malloc( - sizeof(package_info) + (pi->numTypes*sizeof(type_info))); - newpi->numTypes = pi->numTypes; - for (size_t j=0; j<newpi->numTypes; j++) { - size_t cnt = pi->types[j].numEntries; - newpi->types[j].numEntries = cnt; - theme_entry* te = pi->types[j].entries; - if (te != NULL) { - theme_entry* newte = (theme_entry*)malloc(cnt*sizeof(theme_entry)); - newpi->types[j].entries = newte; - memcpy(newte, te, cnt*sizeof(theme_entry)); - } else { - newpi->types[j].entries = NULL; - } - } - return newpi; -} - -status_t ResTable::Theme::applyStyle(uint32_t resID, bool force) -{ - const bag_entry* bag; - uint32_t bagTypeSpecFlags = 0; - mTable.lock(); - const ssize_t N = mTable.getBagLocked(resID, &bag, &bagTypeSpecFlags); - TABLE_NOISY(LOGV("Applying style 0x%08x to theme %p, count=%d", resID, this, N)); - if (N < 0) { - mTable.unlock(); - return N; - } - - uint32_t curPackage = 0xffffffff; - ssize_t curPackageIndex = 0; - package_info* curPI = NULL; - uint32_t curType = 0xffffffff; - size_t numEntries = 0; - theme_entry* curEntries = NULL; - - const bag_entry* end = bag + N; - while (bag < end) { - const uint32_t attrRes = bag->map.name.ident; - const uint32_t p = Res_GETPACKAGE(attrRes); - const uint32_t t = Res_GETTYPE(attrRes); - const uint32_t e = Res_GETENTRY(attrRes); - - if (curPackage != p) { - const ssize_t pidx = mTable.getResourcePackageIndex(attrRes); - if (pidx < 0) { - LOGE("Style contains key with bad package: 0x%08x\n", attrRes); - bag++; - continue; - } - curPackage = p; - curPackageIndex = pidx; - curPI = mPackages[pidx]; - if (curPI == NULL) { - PackageGroup* const grp = mTable.mPackageGroups[pidx]; - int cnt = grp->typeCount; - curPI = (package_info*)malloc( - sizeof(package_info) + (cnt*sizeof(type_info))); - curPI->numTypes = cnt; - memset(curPI->types, 0, cnt*sizeof(type_info)); - mPackages[pidx] = curPI; - } - curType = 0xffffffff; - } - if (curType != t) { - if (t >= curPI->numTypes) { - LOGE("Style contains key with bad type: 0x%08x\n", attrRes); - bag++; - continue; - } - curType = t; - curEntries = curPI->types[t].entries; - if (curEntries == NULL) { - PackageGroup* const grp = mTable.mPackageGroups[curPackageIndex]; - const Type* type = grp->packages[0]->getType(t); - int cnt = type != NULL ? type->entryCount : 0; - curEntries = (theme_entry*)malloc(cnt*sizeof(theme_entry)); - memset(curEntries, Res_value::TYPE_NULL, cnt*sizeof(theme_entry)); - curPI->types[t].numEntries = cnt; - curPI->types[t].entries = curEntries; - } - numEntries = curPI->types[t].numEntries; - } - if (e >= numEntries) { - LOGE("Style contains key with bad entry: 0x%08x\n", attrRes); - bag++; - continue; - } - theme_entry* curEntry = curEntries + e; - TABLE_NOISY(LOGV("Attr 0x%08x: type=0x%x, data=0x%08x; curType=0x%x", - attrRes, bag->map.value.dataType, bag->map.value.data, - curEntry->value.dataType)); - if (force || curEntry->value.dataType == Res_value::TYPE_NULL) { - curEntry->stringBlock = bag->stringBlock; - curEntry->typeSpecFlags |= bagTypeSpecFlags; - curEntry->value = bag->map.value; - } - - bag++; - } - - mTable.unlock(); - - //LOGI("Applying style 0x%08x (force=%d) theme %p...\n", resID, force, this); - //dumpToLog(); - - return NO_ERROR; -} - -status_t ResTable::Theme::setTo(const Theme& other) -{ - //LOGI("Setting theme %p from theme %p...\n", this, &other); - //dumpToLog(); - //other.dumpToLog(); - - if (&mTable == &other.mTable) { - for (size_t i=0; i<Res_MAXPACKAGE; i++) { - if (mPackages[i] != NULL) { - free_package(mPackages[i]); - } - if (other.mPackages[i] != NULL) { - mPackages[i] = copy_package(other.mPackages[i]); - } else { - mPackages[i] = NULL; - } - } - } else { - // @todo: need to really implement this, not just copy - // the system package (which is still wrong because it isn't - // fixing up resource references). - for (size_t i=0; i<Res_MAXPACKAGE; i++) { - if (mPackages[i] != NULL) { - free_package(mPackages[i]); - } - if (i == 0 && other.mPackages[i] != NULL) { - mPackages[i] = copy_package(other.mPackages[i]); - } else { - mPackages[i] = NULL; - } - } - } - - //LOGI("Final theme:"); - //dumpToLog(); - - return NO_ERROR; -} - -ssize_t ResTable::Theme::getAttribute(uint32_t resID, Res_value* outValue, - uint32_t* outTypeSpecFlags) const -{ - int cnt = 20; - - if (outTypeSpecFlags != NULL) *outTypeSpecFlags = 0; - - do { - const ssize_t p = mTable.getResourcePackageIndex(resID); - 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)); - - if (p >= 0) { - const package_info* const pi = mPackages[p]; - if (pi != NULL) { - if (t < pi->numTypes) { - const type_info& ti = pi->types[t]; - if (e < ti.numEntries) { - const theme_entry& te = ti.entries[e]; - if (outTypeSpecFlags != NULL) { - *outTypeSpecFlags |= te.typeSpecFlags; - } - const uint8_t type = te.value.dataType; - if (type == Res_value::TYPE_ATTRIBUTE) { - if (cnt > 0) { - cnt--; - resID = te.value.data; - continue; - } - LOGW("Too many attribute references, stopped at: 0x%08x\n", resID); - return BAD_INDEX; - } else if (type != Res_value::TYPE_NULL) { - *outValue = te.value; - return te.stringBlock; - } - return BAD_INDEX; - } - } - } - } - break; - - } while (true); - - return BAD_INDEX; -} - -ssize_t ResTable::Theme::resolveAttributeReference(Res_value* inOutValue, - ssize_t blockIndex, uint32_t* outLastRef, - uint32_t* inoutTypeSpecFlags) const -{ - //printf("Resolving type=0x%x\n", inOutValue->dataType); - if (inOutValue->dataType == Res_value::TYPE_ATTRIBUTE) { - uint32_t newTypeSpecFlags; - blockIndex = getAttribute(inOutValue->data, inOutValue, &newTypeSpecFlags); - if (inoutTypeSpecFlags != NULL) *inoutTypeSpecFlags |= newTypeSpecFlags; - //printf("Retrieved attribute new type=0x%x\n", inOutValue->dataType); - if (blockIndex < 0) { - return blockIndex; - } - } - return mTable.resolveReference(inOutValue, blockIndex, outLastRef); -} - -void ResTable::Theme::dumpToLog() const -{ - LOGI("Theme %p:\n", this); - for (size_t i=0; i<Res_MAXPACKAGE; i++) { - package_info* pi = mPackages[i]; - if (pi == NULL) continue; - - LOGI(" Package #0x%02x:\n", (int)(i+1)); - for (size_t j=0; j<pi->numTypes; j++) { - type_info& ti = pi->types[j]; - if (ti.numEntries == 0) continue; - - LOGI(" Type #0x%02x:\n", (int)(j+1)); - for (size_t k=0; k<ti.numEntries; k++) { - theme_entry& te = ti.entries[k]; - if (te.value.dataType == Res_value::TYPE_NULL) continue; - LOGI(" 0x%08x: t=0x%x, d=0x%08x (block=%d)\n", - (int)Res_MAKEID(i, j, k), - te.value.dataType, (int)te.value.data, (int)te.stringBlock); - } - } - } -} - -ResTable::ResTable() - : mError(NO_INIT) -{ - memset(&mParams, 0, sizeof(mParams)); - memset(mPackageMap, 0, sizeof(mPackageMap)); - //LOGI("Creating ResTable %p\n", this); -} - -ResTable::ResTable(const void* data, size_t size, void* cookie, bool copyData) - : mError(NO_INIT) -{ - memset(&mParams, 0, sizeof(mParams)); - memset(mPackageMap, 0, sizeof(mPackageMap)); - add(data, size, cookie, copyData); - LOG_FATAL_IF(mError != NO_ERROR, "Error parsing resource table"); - //LOGI("Creating ResTable %p\n", this); -} - -ResTable::~ResTable() -{ - //LOGI("Destroying ResTable in %p\n", this); - uninit(); -} - -inline ssize_t ResTable::getResourcePackageIndex(uint32_t resID) const -{ - return ((ssize_t)mPackageMap[Res_GETPACKAGE(resID)+1])-1; -} - -status_t ResTable::add(const void* data, size_t size, void* cookie, bool copyData) -{ - return add(data, size, cookie, NULL, copyData); -} - -status_t ResTable::add(Asset* asset, void* cookie, bool copyData) -{ - const void* data = asset->getBuffer(true); - if (data == NULL) { - LOGW("Unable to get buffer of resource asset file"); - return UNKNOWN_ERROR; - } - size_t size = (size_t)asset->getLength(); - return add(data, size, cookie, asset, copyData); -} - -status_t ResTable::add(const void* data, size_t size, void* cookie, - Asset* asset, bool copyData) -{ - if (!data) return NO_ERROR; - Header* header = new Header; - header->index = mHeaders.size(); - header->cookie = cookie; - mHeaders.add(header); - - const bool notDeviceEndian = htods(0xf0) != 0xf0; - - LOAD_TABLE_NOISY( - LOGV("Adding resources to ResTable: data=%p, size=0x%x, cookie=%p, asset=%p, copy=%d\n", - data, size, cookie, asset, copyData)); - - if (copyData || notDeviceEndian) { - header->ownedData = malloc(size); - if (header->ownedData == NULL) { - return (mError=NO_MEMORY); - } - memcpy(header->ownedData, data, size); - data = header->ownedData; - } - - header->header = (const ResTable_header*)data; - header->size = dtohl(header->header->header.size); - //LOGI("Got size 0x%x, again size 0x%x, raw size 0x%x\n", header->size, - // dtohl(header->header->header.size), header->header->header.size); - LOAD_TABLE_NOISY(LOGV("Loading ResTable @%p:\n", header->header)); - LOAD_TABLE_NOISY(printHexData(2, header->header, header->size < 256 ? header->size : 256, - 16, 16, 0, false, printToLogFunc)); - if (dtohs(header->header->header.headerSize) > header->size - || header->size > size) { - LOGW("Bad resource table: header size 0x%x or total size 0x%x is larger than data size 0x%x\n", - (int)dtohs(header->header->header.headerSize), - (int)header->size, (int)size); - return (mError=BAD_TYPE); - } - if (((dtohs(header->header->header.headerSize)|header->size)&0x3) != 0) { - LOGW("Bad resource table: header size 0x%x or total size 0x%x is not on an integer boundary\n", - (int)dtohs(header->header->header.headerSize), - (int)header->size); - return (mError=BAD_TYPE); - } - header->dataEnd = ((const uint8_t*)header->header) + header->size; - - // Iterate through all chunks. - size_t curPackage = 0; - - const ResChunk_header* chunk = - (const ResChunk_header*)(((const uint8_t*)header->header) - + dtohs(header->header->header.headerSize)); - while (((const uint8_t*)chunk) <= (header->dataEnd-sizeof(ResChunk_header)) && - ((const uint8_t*)chunk) <= (header->dataEnd-dtohl(chunk->size))) { - status_t err = validate_chunk(chunk, sizeof(ResChunk_header), header->dataEnd, "ResTable"); - if (err != NO_ERROR) { - return (mError=err); - } - TABLE_NOISY(LOGV("Chunk: type=0x%x, headerSize=0x%x, size=0x%x, pos=%p\n", - dtohs(chunk->type), dtohs(chunk->headerSize), dtohl(chunk->size), - (void*)(((const uint8_t*)chunk) - ((const uint8_t*)header->header)))); - const size_t csize = dtohl(chunk->size); - const uint16_t ctype = dtohs(chunk->type); - if (ctype == RES_STRING_POOL_TYPE) { - if (header->values.getError() != NO_ERROR) { - // Only use the first string chunk; ignore any others that - // may appear. - status_t err = header->values.setTo(chunk, csize); - if (err != NO_ERROR) { - return (mError=err); - } - } else { - LOGW("Multiple string chunks found in resource table."); - } - } else if (ctype == RES_TABLE_PACKAGE_TYPE) { - if (curPackage >= dtohl(header->header->packageCount)) { - LOGW("More package chunks were found than the %d declared in the header.", - dtohl(header->header->packageCount)); - return (mError=BAD_TYPE); - } - if (parsePackage((ResTable_package*)chunk, header) != NO_ERROR) { - return mError; - } - curPackage++; - } else { - LOGW("Unknown chunk type %p in table at %p.\n", - (void*)(int)(ctype), - (void*)(((const uint8_t*)chunk) - ((const uint8_t*)header->header))); - } - chunk = (const ResChunk_header*) - (((const uint8_t*)chunk) + csize); - } - - if (curPackage < dtohl(header->header->packageCount)) { - LOGW("Fewer package chunks (%d) were found than the %d declared in the header.", - (int)curPackage, dtohl(header->header->packageCount)); - return (mError=BAD_TYPE); - } - mError = header->values.getError(); - if (mError != NO_ERROR) { - LOGW("No string values found in resource table!"); - } - TABLE_NOISY(LOGV("Returning from add with mError=%d\n", mError)); - return mError; -} - -status_t ResTable::getError() const -{ - return mError; -} - -void ResTable::uninit() -{ - mError = NO_INIT; - size_t N = mPackageGroups.size(); - for (size_t i=0; i<N; i++) { - PackageGroup* g = mPackageGroups[i]; - delete g; - } - N = mHeaders.size(); - for (size_t i=0; i<N; i++) { - Header* header = mHeaders[i]; - if (header->ownedData) { - free(header->ownedData); - } - delete header; - } - - mPackageGroups.clear(); - mHeaders.clear(); -} - -bool ResTable::getResourceName(uint32_t resID, resource_name* outName) const -{ - if (mError != NO_ERROR) { - return false; - } - - const ssize_t p = getResourcePackageIndex(resID); - const int t = Res_GETTYPE(resID); - const int e = Res_GETENTRY(resID); - - if (p < 0) { - LOGW("No package identifier when getting name for resource number 0x%08x", resID); - return false; - } - if (t < 0) { - LOGW("No type identifier when getting name for resource number 0x%08x", resID); - return false; - } - - const PackageGroup* const grp = mPackageGroups[p]; - if (grp == NULL) { - LOGW("Bad identifier when getting name for resource number 0x%08x", resID); - return false; - } - if (grp->packages.size() > 0) { - const Package* const package = grp->packages[0]; - - const ResTable_type* type; - const ResTable_entry* entry; - ssize_t offset = getEntry(package, t, e, NULL, &type, &entry, NULL); - if (offset <= 0) { - return false; - } - - outName->package = grp->name.string(); - outName->packageLen = grp->name.size(); - outName->type = grp->typeStrings.stringAt(t, &outName->typeLen); - outName->name = grp->keyStrings.stringAt( - dtohl(entry->key.index), &outName->nameLen); - return true; - } - - return false; -} - -ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, - uint32_t* outSpecFlags, ResTable_config* outConfig) const -{ - if (mError != NO_ERROR) { - return mError; - } - - const ssize_t p = getResourcePackageIndex(resID); - const int t = Res_GETTYPE(resID); - const int e = Res_GETENTRY(resID); - - if (p < 0) { - LOGW("No package identifier when getting value for resource number 0x%08x", resID); - return BAD_INDEX; - } - if (t < 0) { - LOGW("No type identifier when getting value for resource number 0x%08x", resID); - return BAD_INDEX; - } - - const Res_value* bestValue = NULL; - const Package* bestPackage = NULL; - ResTable_config bestItem; - memset(&bestItem, 0, sizeof(bestItem)); // make the compiler shut up - - if (outSpecFlags != NULL) *outSpecFlags = 0; - - // Look through all resource packages, starting with the most - // recently added. - const PackageGroup* const grp = mPackageGroups[p]; - if (grp == NULL) { - LOGW("Bad identifier when getting value for resource number 0x%08x", resID); - return false; - } - size_t ip = grp->packages.size(); - while (ip > 0) { - ip--; - - const Package* const package = grp->packages[ip]; - - const ResTable_type* type; - const ResTable_entry* entry; - const Type* typeClass; - ssize_t offset = getEntry(package, t, e, &mParams, &type, &entry, &typeClass); - if (offset <= 0) { - if (offset < 0) { - LOGW("Failure getting entry for 0x%08x (t=%d e=%d) in package %d: 0x%08x\n", - resID, t, e, (int)ip, (int)offset); - return offset; - } - continue; - } - - if ((dtohs(entry->flags)&entry->FLAG_COMPLEX) != 0) { - if (!mayBeBag) { - LOGW("Requesting resource %p failed because it is complex\n", - (void*)resID); - } - continue; - } - - TABLE_NOISY(aout << "Resource type data: " - << HexDump(type, dtohl(type->header.size)) << endl); - - if ((size_t)offset > (dtohl(type->header.size)-sizeof(Res_value))) { - LOGW("ResTable_item at %d is beyond type chunk data %d", - (int)offset, dtohl(type->header.size)); - return BAD_TYPE; - } - - const Res_value* item = - (const Res_value*)(((const uint8_t*)type) + offset); - ResTable_config thisConfig; - thisConfig.copyFromDtoH(type->config); - - if (outSpecFlags != NULL) { - if (typeClass->typeSpecFlags != NULL) { - *outSpecFlags |= dtohl(typeClass->typeSpecFlags[e]); - } else { - *outSpecFlags = -1; - } - } - - if (bestPackage != NULL && bestItem.isBetterThan(thisConfig)) { - continue; - } - - bestItem = thisConfig; - bestValue = item; - bestPackage = package; - } - - TABLE_NOISY(printf("Found result: package %p\n", bestPackage)); - - if (bestValue) { - outValue->size = dtohs(bestValue->size); - outValue->res0 = bestValue->res0; - outValue->dataType = bestValue->dataType; - outValue->data = dtohl(bestValue->data); - if (outConfig != NULL) { - *outConfig = bestItem; - } - TABLE_NOISY(size_t len; - printf("Found value: pkg=%d, type=%d, str=%s, int=%d\n", - bestPackage->header->index, - outValue->dataType, - outValue->dataType == bestValue->TYPE_STRING - ? String8(bestPackage->header->values.stringAt( - outValue->data, &len)).string() - : "", - outValue->data)); - return bestPackage->header->index; - } - - return BAD_INDEX; -} - -ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex, - uint32_t* outLastRef, uint32_t* inoutTypeSpecFlags) const -{ - int count=0; - while (blockIndex >= 0 && value->dataType == value->TYPE_REFERENCE - && value->data != 0 && count < 20) { - if (outLastRef) *outLastRef = value->data; - uint32_t lastRef = value->data; - uint32_t newFlags = 0; - const ssize_t newIndex = getResource(value->data, value, true, &newFlags); - //LOGI("Resolving reference d=%p: newIndex=%d, t=0x%02x, d=%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) { - // This can fail if the resource being referenced is a style... - // in this case, just return the reference, and expect the - // caller to deal with. - return blockIndex; - } - blockIndex = newIndex; - count++; - } - return blockIndex; -} - -const char16_t* ResTable::valueToString( - const Res_value* value, size_t stringBlock, - char16_t tmpBuffer[TMP_BUFFER_SIZE], size_t* outLen) -{ - if (!value) { - return NULL; - } - if (value->dataType == value->TYPE_STRING) { - return getTableStringBlock(stringBlock)->stringAt(value->data, outLen); - } - // XXX do int to string conversions. - return NULL; -} - -ssize_t ResTable::lockBag(uint32_t resID, const bag_entry** outBag) const -{ - mLock.lock(); - ssize_t err = getBagLocked(resID, outBag); - if (err < NO_ERROR) { - //printf("*** get failed! unlocking\n"); - mLock.unlock(); - } - return err; -} - -void ResTable::unlockBag(const bag_entry* bag) const -{ - //printf("<<< unlockBag %p\n", this); - mLock.unlock(); -} - -void ResTable::lock() const -{ - mLock.lock(); -} - -void ResTable::unlock() const -{ - mLock.unlock(); -} - -ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag, - uint32_t* outTypeSpecFlags) const -{ - if (mError != NO_ERROR) { - return mError; - } - - const ssize_t p = getResourcePackageIndex(resID); - const int t = Res_GETTYPE(resID); - const int e = Res_GETENTRY(resID); - - if (p < 0) { - LOGW("Invalid package identifier when getting bag for resource number 0x%08x", resID); - return BAD_INDEX; - } - if (t < 0) { - LOGW("No type identifier when getting bag for resource number 0x%08x", resID); - return BAD_INDEX; - } - - //printf("Get bag: id=0x%08x, p=%d, t=%d\n", resID, p, t); - PackageGroup* const grp = mPackageGroups[p]; - if (grp == NULL) { - LOGW("Bad identifier when getting bag for resource number 0x%08x", resID); - return false; - } - - if (t >= (int)grp->typeCount) { - LOGW("Type identifier 0x%x is larger than type count 0x%x", - t+1, (int)grp->typeCount); - return BAD_INDEX; - } - - const Package* const basePackage = grp->packages[0]; - - const Type* const typeConfigs = basePackage->getType(t); - - const size_t NENTRY = typeConfigs->entryCount; - if (e >= (int)NENTRY) { - LOGW("Entry identifier 0x%x is larger than entry count 0x%x", - e, (int)typeConfigs->entryCount); - return BAD_INDEX; - } - - // First see if we've already computed this bag... - if (grp->bags) { - bag_set** typeSet = grp->bags[t]; - if (typeSet) { - bag_set* set = typeSet[e]; - if (set) { - if (set != (bag_set*)0xFFFFFFFF) { - if (outTypeSpecFlags != NULL) { - *outTypeSpecFlags = set->typeSpecFlags; - } - *outBag = (bag_entry*)(set+1); - //LOGI("Found existing bag for: %p\n", (void*)resID); - return set->numAttrs; - } - LOGW("Attempt to retrieve bag 0x%08x which is invalid or in a cycle.", - resID); - return BAD_INDEX; - } - } - } - - // Bag not found, we need to compute it! - if (!grp->bags) { - grp->bags = (bag_set***)malloc(sizeof(bag_set*)*grp->typeCount); - if (!grp->bags) return NO_MEMORY; - memset(grp->bags, 0, sizeof(bag_set*)*grp->typeCount); - } - - bag_set** typeSet = grp->bags[t]; - if (!typeSet) { - typeSet = (bag_set**)malloc(sizeof(bag_set*)*NENTRY); - if (!typeSet) return NO_MEMORY; - memset(typeSet, 0, sizeof(bag_set*)*NENTRY); - grp->bags[t] = typeSet; - } - - // Mark that we are currently working on this one. - typeSet[e] = (bag_set*)0xFFFFFFFF; - - // This is what we are building. - bag_set* set = NULL; - - TABLE_NOISY(LOGI("Building bag: %p\n", (void*)resID)); - - // Now collect all bag attributes from all packages. - size_t ip = grp->packages.size(); - while (ip > 0) { - ip--; - - const Package* const package = grp->packages[ip]; - - const ResTable_type* type; - const ResTable_entry* entry; - const Type* typeClass; - LOGV("Getting entry pkg=%p, t=%d, e=%d\n", package, t, e); - ssize_t offset = getEntry(package, t, e, &mParams, &type, &entry, &typeClass); - LOGV("Resulting offset=%d\n", offset); - if (offset <= 0) { - if (offset < 0) { - if (set) free(set); - return offset; - } - continue; - } - - if ((dtohs(entry->flags)&entry->FLAG_COMPLEX) == 0) { - LOGW("Skipping entry %p in package table %d because it is not complex!\n", - (void*)resID, (int)ip); - continue; - } - - const uint16_t entrySize = dtohs(entry->size); - const uint32_t parent = entrySize >= sizeof(ResTable_map_entry) - ? dtohl(((const ResTable_map_entry*)entry)->parent.ident) : 0; - const uint32_t count = entrySize >= sizeof(ResTable_map_entry) - ? dtohl(((const ResTable_map_entry*)entry)->count) : 0; - - size_t N = count; - - TABLE_NOISY(LOGI("Found map: size=%p parent=%p count=%d\n", - entrySize, parent, count)); - - if (set == NULL) { - // If this map inherits from another, we need to start - // with its parent's values. Otherwise start out empty. - TABLE_NOISY(printf("Creating new bag, entrySize=0x%08x, parent=0x%08x\n", - entrySize, parent)); - if (parent) { - const bag_entry* parentBag; - uint32_t parentTypeSpecFlags = 0; - const ssize_t NP = getBagLocked(parent, &parentBag, &parentTypeSpecFlags); - const size_t NT = ((NP >= 0) ? NP : 0) + N; - set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*NT); - if (set == NULL) { - return NO_MEMORY; - } - if (NP > 0) { - memcpy(set+1, parentBag, NP*sizeof(bag_entry)); - set->numAttrs = NP; - TABLE_NOISY(LOGI("Initialized new bag with %d inherited attributes.\n", NP)); - } else { - TABLE_NOISY(LOGI("Initialized new bag with no inherited attributes.\n")); - set->numAttrs = 0; - } - set->availAttrs = NT; - set->typeSpecFlags = parentTypeSpecFlags; - } else { - set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*N); - if (set == NULL) { - return NO_MEMORY; - } - set->numAttrs = 0; - set->availAttrs = N; - set->typeSpecFlags = 0; - } - } - - if (typeClass->typeSpecFlags != NULL) { - set->typeSpecFlags |= dtohl(typeClass->typeSpecFlags[e]); - } else { - set->typeSpecFlags = -1; - } - - // Now merge in the new attributes... - ssize_t curOff = offset; - const ResTable_map* map; - bag_entry* entries = (bag_entry*)(set+1); - size_t curEntry = 0; - uint32_t pos = 0; - TABLE_NOISY(LOGI("Starting with set %p, entries=%p, avail=%d\n", - set, entries, set->availAttrs)); - while (pos < count) { - TABLE_NOISY(printf("Now at %p\n", (void*)curOff)); - - if ((size_t)curOff > (dtohl(type->header.size)-sizeof(ResTable_map))) { - LOGW("ResTable_map at %d is beyond type chunk data %d", - (int)curOff, dtohl(type->header.size)); - return BAD_TYPE; - } - map = (const ResTable_map*)(((const uint8_t*)type) + curOff); - N++; - - const uint32_t newName = htodl(map->name.ident); - bool isInside; - uint32_t oldName = 0; - while ((isInside=(curEntry < set->numAttrs)) - && (oldName=entries[curEntry].map.name.ident) < newName) { - TABLE_NOISY(printf("#%d: Keeping existing attribute: 0x%08x\n", - curEntry, entries[curEntry].map.name.ident)); - curEntry++; - } - - if ((!isInside) || oldName != newName) { - // This is a new attribute... figure out what to do with it. - if (set->numAttrs >= set->availAttrs) { - // Need to alloc more memory... - const size_t newAvail = set->availAttrs+N; - set = (bag_set*)realloc(set, - sizeof(bag_set) - + sizeof(bag_entry)*newAvail); - if (set == NULL) { - return NO_MEMORY; - } - set->availAttrs = newAvail; - entries = (bag_entry*)(set+1); - TABLE_NOISY(printf("Reallocated set %p, entries=%p, avail=%d\n", - set, entries, set->availAttrs)); - } - if (isInside) { - // Going in the middle, need to make space. - memmove(entries+curEntry+1, entries+curEntry, - sizeof(bag_entry)*(set->numAttrs-curEntry)); - set->numAttrs++; - } - TABLE_NOISY(printf("#%d: Inserting new attribute: 0x%08x\n", - curEntry, newName)); - } else { - TABLE_NOISY(printf("#%d: Replacing existing attribute: 0x%08x\n", - curEntry, oldName)); - } - - bag_entry* cur = entries+curEntry; - - cur->stringBlock = package->header->index; - cur->map.name.ident = newName; - cur->map.value.copyFrom_dtoh(map->value); - TABLE_NOISY(printf("Setting entry #%d %p: block=%d, name=0x%08x, type=%d, data=0x%08x\n", - curEntry, cur, cur->stringBlock, cur->map.name.ident, - cur->map.value.dataType, cur->map.value.data)); - - // On to the next! - curEntry++; - pos++; - const size_t size = dtohs(map->value.size); - curOff += size + sizeof(*map)-sizeof(map->value); - }; - if (curEntry > set->numAttrs) { - set->numAttrs = curEntry; - } - } - - // And this is it... - typeSet[e] = set; - if (set) { - if (outTypeSpecFlags != NULL) { - *outTypeSpecFlags = set->typeSpecFlags; - } - *outBag = (bag_entry*)(set+1); - TABLE_NOISY(LOGI("Returning %d attrs\n", set->numAttrs)); - return set->numAttrs; - } - return BAD_INDEX; -} - -void ResTable::setParameters(const ResTable_config* params) -{ - mLock.lock(); - TABLE_GETENTRY(LOGI("Setting parameters: imsi:%d/%d lang:%c%c cnt:%c%c " - "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n", - params->mcc, params->mnc, - params->language[0] ? params->language[0] : '-', - params->language[1] ? params->language[1] : '-', - params->country[0] ? params->country[0] : '-', - params->country[1] ? params->country[1] : '-', - params->orientation, - params->touchscreen, - params->density, - params->keyboard, - params->inputFlags, - params->navigation, - params->screenWidth, - params->screenHeight)); - mParams = *params; - for (size_t i=0; i<mPackageGroups.size(); i++) { - TABLE_NOISY(LOGI("CLEARING BAGS FOR GROUP %d!", i)); - mPackageGroups[i]->clearBagCache(); - } - mLock.unlock(); -} - -void ResTable::getParameters(ResTable_config* params) const -{ - mLock.lock(); - *params = mParams; - mLock.unlock(); -} - -struct id_name_map { - uint32_t id; - size_t len; - char16_t name[6]; -}; - -const static id_name_map ID_NAMES[] = { - { ResTable_map::ATTR_TYPE, 5, { '^', 't', 'y', 'p', 'e' } }, - { ResTable_map::ATTR_L10N, 5, { '^', 'l', '1', '0', 'n' } }, - { ResTable_map::ATTR_MIN, 4, { '^', 'm', 'i', 'n' } }, - { ResTable_map::ATTR_MAX, 4, { '^', 'm', 'a', 'x' } }, - { ResTable_map::ATTR_OTHER, 6, { '^', 'o', 't', 'h', 'e', 'r' } }, - { ResTable_map::ATTR_ZERO, 5, { '^', 'z', 'e', 'r', 'o' } }, - { ResTable_map::ATTR_ONE, 4, { '^', 'o', 'n', 'e' } }, - { ResTable_map::ATTR_TWO, 4, { '^', 't', 'w', 'o' } }, - { ResTable_map::ATTR_FEW, 4, { '^', 'f', 'e', 'w' } }, - { ResTable_map::ATTR_MANY, 5, { '^', 'm', 'a', 'n', 'y' } }, -}; - -uint32_t ResTable::identifierForName(const char16_t* name, size_t nameLen, - const char16_t* type, size_t typeLen, - const char16_t* package, - size_t packageLen, - uint32_t* outTypeSpecFlags) const -{ - TABLE_SUPER_NOISY(printf("Identifier for name: error=%d\n", mError)); - - // Check for internal resource identifier as the very first thing, so - // that we will always find them even when there are no resources. - if (name[0] == '^') { - const int N = (sizeof(ID_NAMES)/sizeof(ID_NAMES[0])); - size_t len; - for (int i=0; i<N; i++) { - const id_name_map* m = ID_NAMES + i; - len = m->len; - if (len != nameLen) { - continue; - } - for (size_t j=1; j<len; j++) { - if (m->name[j] != name[j]) { - goto nope; - } - } - return m->id; -nope: - ; - } - if (nameLen > 7) { - if (name[1] == 'i' && name[2] == 'n' - && name[3] == 'd' && name[4] == 'e' && name[5] == 'x' - && name[6] == '_') { - int index = atoi(String8(name + 7, nameLen - 7).string()); - if (Res_CHECKID(index)) { - LOGW("Array resource index: %d is too large.", - index); - return 0; - } - return Res_MAKEARRAY(index); - } - } - return 0; - } - - if (mError != NO_ERROR) { - return 0; - } - - // Figure out the package and type we are looking in... - - const char16_t* packageEnd = NULL; - const char16_t* typeEnd = NULL; - const char16_t* const nameEnd = name+nameLen; - const char16_t* p = name; - while (p < nameEnd) { - if (*p == ':') packageEnd = p; - else if (*p == '/') typeEnd = p; - p++; - } - if (*name == '@') name++; - if (name >= nameEnd) { - return 0; - } - - if (packageEnd) { - package = name; - packageLen = packageEnd-name; - name = packageEnd+1; - } else if (!package) { - return 0; - } - - if (typeEnd) { - type = name; - typeLen = typeEnd-name; - name = typeEnd+1; - } else if (!type) { - return 0; - } - - if (name >= nameEnd) { - return 0; - } - nameLen = nameEnd-name; - - TABLE_NOISY(printf("Looking for identifier: type=%s, name=%s, package=%s\n", - String8(type, typeLen).string(), - String8(name, nameLen).string(), - String8(package, packageLen).string())); - - const size_t NG = mPackageGroups.size(); - for (size_t ig=0; ig<NG; ig++) { - const PackageGroup* group = mPackageGroups[ig]; - - if (strzcmp16(package, packageLen, - group->name.string(), group->name.size())) { - TABLE_NOISY(printf("Skipping package group: %s\n", String8(group->name).string())); - continue; - } - - const ssize_t ti = group->typeStrings.indexOfString(type, typeLen); - if (ti < 0) { - TABLE_NOISY(printf("Type not found in package %s\n", String8(group->name).string())); - continue; - } - - const ssize_t ei = group->keyStrings.indexOfString(name, nameLen); - if (ei < 0) { - TABLE_NOISY(printf("Name not found in package %s\n", String8(group->name).string())); - continue; - } - - TABLE_NOISY(printf("Search indices: type=%d, name=%d\n", ti, ei)); - - const Type* const typeConfigs = group->packages[0]->getType(ti); - if (typeConfigs == NULL || typeConfigs->configs.size() <= 0) { - TABLE_NOISY(printf("Expected type structure not found in package %s for idnex %d\n", - String8(group->name).string(), ti)); - } - - size_t NTC = typeConfigs->configs.size(); - for (size_t tci=0; tci<NTC; tci++) { - const ResTable_type* const ty = typeConfigs->configs[tci]; - const uint32_t typeOffset = dtohl(ty->entriesStart); - - const uint8_t* const end = ((const uint8_t*)ty) + dtohl(ty->header.size); - const uint32_t* const eindex = (const uint32_t*) - (((const uint8_t*)ty) + dtohs(ty->header.headerSize)); - - const size_t NE = dtohl(ty->entryCount); - for (size_t i=0; i<NE; i++) { - uint32_t offset = dtohl(eindex[i]); - if (offset == ResTable_type::NO_ENTRY) { - continue; - } - - offset += typeOffset; - - if (offset > (dtohl(ty->header.size)-sizeof(ResTable_entry))) { - LOGW("ResTable_entry at %d is beyond type chunk data %d", - offset, dtohl(ty->header.size)); - return 0; - } - if ((offset&0x3) != 0) { - LOGW("ResTable_entry at %d (pkg=%d type=%d ent=%d) is not on an integer boundary when looking for %s:%s/%s", - (int)offset, (int)group->id, (int)ti+1, (int)i, - String8(package, packageLen).string(), - String8(type, typeLen).string(), - String8(name, nameLen).string()); - return 0; - } - - const ResTable_entry* const entry = (const ResTable_entry*) - (((const uint8_t*)ty) + offset); - if (dtohs(entry->size) < sizeof(*entry)) { - LOGW("ResTable_entry size %d is too small", dtohs(entry->size)); - return BAD_TYPE; - } - - TABLE_SUPER_NOISY(printf("Looking at entry #%d: want str %d, have %d\n", - i, ei, dtohl(entry->key.index))); - if (dtohl(entry->key.index) == (size_t)ei) { - if (outTypeSpecFlags) { - *outTypeSpecFlags = typeConfigs->typeSpecFlags[i]; - } - return Res_MAKEID(group->id-1, ti, i); - } - } - } - } - - return 0; -} - -bool ResTable::expandResourceRef(const uint16_t* refStr, size_t refLen, - String16* outPackage, - String16* outType, - String16* outName, - const String16* defType, - const String16* defPackage, - const char** outErrorMsg) -{ - const char16_t* packageEnd = NULL; - const char16_t* typeEnd = NULL; - const char16_t* p = refStr; - const char16_t* const end = p + refLen; - while (p < end) { - if (*p == ':') packageEnd = p; - else if (*p == '/') { - typeEnd = p; - break; - } - p++; - } - p = refStr; - if (*p == '@') p++; - - if (packageEnd) { - *outPackage = String16(p, packageEnd-p); - p = packageEnd+1; - } else { - if (!defPackage) { - if (outErrorMsg) { - *outErrorMsg = "No resource package specified"; - } - return false; - } - *outPackage = *defPackage; - } - if (typeEnd) { - *outType = String16(p, typeEnd-p); - p = typeEnd+1; - } else { - if (!defType) { - if (outErrorMsg) { - *outErrorMsg = "No resource type specified"; - } - return false; - } - *outType = *defType; - } - *outName = String16(p, end-p); - return true; -} - -static uint32_t get_hex(char c, bool* outError) -{ - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return c - 'a' + 0xa; - } else if (c >= 'A' && c <= 'F') { - return c - 'A' + 0xa; - } - *outError = true; - return 0; -} - -struct unit_entry -{ - const char* name; - size_t len; - uint8_t type; - uint32_t unit; - float scale; -}; - -static const unit_entry unitNames[] = { - { "px", strlen("px"), Res_value::TYPE_DIMENSION, Res_value::COMPLEX_UNIT_PX, 1.0f }, - { "dip", strlen("dip"), Res_value::TYPE_DIMENSION, Res_value::COMPLEX_UNIT_DIP, 1.0f }, - { "dp", strlen("dp"), Res_value::TYPE_DIMENSION, Res_value::COMPLEX_UNIT_DIP, 1.0f }, - { "sp", strlen("sp"), Res_value::TYPE_DIMENSION, Res_value::COMPLEX_UNIT_SP, 1.0f }, - { "pt", strlen("pt"), Res_value::TYPE_DIMENSION, Res_value::COMPLEX_UNIT_PT, 1.0f }, - { "in", strlen("in"), Res_value::TYPE_DIMENSION, Res_value::COMPLEX_UNIT_IN, 1.0f }, - { "mm", strlen("mm"), Res_value::TYPE_DIMENSION, Res_value::COMPLEX_UNIT_MM, 1.0f }, - { "%", strlen("%"), Res_value::TYPE_FRACTION, Res_value::COMPLEX_UNIT_FRACTION, 1.0f/100 }, - { "%p", strlen("%p"), Res_value::TYPE_FRACTION, Res_value::COMPLEX_UNIT_FRACTION_PARENT, 1.0f/100 }, - { NULL, 0, 0, 0, 0 } -}; - -static bool parse_unit(const char* str, Res_value* outValue, - float* outScale, const char** outEnd) -{ - const char* end = str; - while (*end != 0 && !isspace((unsigned char)*end)) { - end++; - } - const size_t len = end-str; - - const char* realEnd = end; - while (*realEnd != 0 && isspace((unsigned char)*realEnd)) { - realEnd++; - } - if (*realEnd != 0) { - return false; - } - - const unit_entry* cur = unitNames; - while (cur->name) { - if (len == cur->len && strncmp(cur->name, str, len) == 0) { - outValue->dataType = cur->type; - outValue->data = cur->unit << Res_value::COMPLEX_UNIT_SHIFT; - *outScale = cur->scale; - *outEnd = end; - //printf("Found unit %s for %s\n", cur->name, str); - return true; - } - cur++; - } - - return false; -} - - -bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) -{ - while (len > 0 && isspace16(*s)) { - s++; - len--; - } - - if (len <= 0) { - return false; - } - - size_t i = 0; - int32_t val = 0; - bool neg = false; - - if (*s == '-') { - neg = true; - i++; - } - - if (s[i] < '0' || s[i] > '9') { - return false; - } - - // Decimal or hex? - if (s[i] == '0' && s[i+1] == 'x') { - if (outValue) - outValue->dataType = outValue->TYPE_INT_HEX; - i += 2; - bool error = false; - while (i < len && !error) { - val = (val*16) + get_hex(s[i], &error); - i++; - } - if (error) { - return false; - } - } else { - if (outValue) - outValue->dataType = outValue->TYPE_INT_DEC; - while (i < len) { - if (s[i] < '0' || s[i] > '9') { - return false; - } - val = (val*10) + s[i]-'0'; - i++; - } - } - - if (neg) val = -val; - - while (i < len && isspace16(s[i])) { - i++; - } - - if (i == len) { - if (outValue) - outValue->data = val; - return true; - } - - return false; -} - -bool ResTable::stringToFloat(const char16_t* s, size_t len, Res_value* outValue) -{ - while (len > 0 && isspace16(*s)) { - s++; - len--; - } - - if (len <= 0) { - return false; - } - - char buf[128]; - int i=0; - while (len > 0 && *s != 0 && i < 126) { - if (*s > 255) { - return false; - } - buf[i++] = *s++; - len--; - } - - if (len > 0) { - return false; - } - if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.') { - return false; - } - - buf[i] = 0; - const char* end; - float f = strtof(buf, (char**)&end); - - if (*end != 0 && !isspace((unsigned char)*end)) { - // Might be a unit... - float scale; - if (parse_unit(end, outValue, &scale, &end)) { - f *= scale; - const bool neg = f < 0; - if (neg) f = -f; - uint64_t bits = (uint64_t)(f*(1<<23)+.5f); - uint32_t radix; - uint32_t shift; - if ((bits&0x7fffff) == 0) { - // Always use 23p0 if there is no fraction, just to make - // things easier to read. - radix = Res_value::COMPLEX_RADIX_23p0; - shift = 23; - } else if ((bits&0xffffffffff800000LL) == 0) { - // Magnitude is zero -- can fit in 0 bits of precision. - radix = Res_value::COMPLEX_RADIX_0p23; - shift = 0; - } else if ((bits&0xffffffff80000000LL) == 0) { - // Magnitude can fit in 8 bits of precision. - radix = Res_value::COMPLEX_RADIX_8p15; - shift = 8; - } else if ((bits&0xffffff8000000000LL) == 0) { - // Magnitude can fit in 16 bits of precision. - radix = Res_value::COMPLEX_RADIX_16p7; - shift = 16; - } else { - // Magnitude needs entire range, so no fractional part. - radix = Res_value::COMPLEX_RADIX_23p0; - shift = 23; - } - int32_t mantissa = (int32_t)( - (bits>>shift) & Res_value::COMPLEX_MANTISSA_MASK); - if (neg) { - mantissa = (-mantissa) & Res_value::COMPLEX_MANTISSA_MASK; - } - outValue->data |= - (radix<<Res_value::COMPLEX_RADIX_SHIFT) - | (mantissa<<Res_value::COMPLEX_MANTISSA_SHIFT); - //printf("Input value: %f 0x%016Lx, mult: %f, radix: %d, shift: %d, final: 0x%08x\n", - // f * (neg ? -1 : 1), bits, f*(1<<23), - // radix, shift, outValue->data); - return true; - } - return false; - } - - while (*end != 0 && isspace((unsigned char)*end)) { - end++; - } - - if (*end == 0) { - if (outValue) { - outValue->dataType = outValue->TYPE_FLOAT; - *(float*)(&outValue->data) = f; - return true; - } - } - - return false; -} - -bool ResTable::stringToValue(Res_value* outValue, String16* outString, - const char16_t* s, size_t len, - bool preserveSpaces, bool coerceType, - uint32_t attrID, - const String16* defType, - const String16* defPackage, - Accessor* accessor, - void* accessorCookie, - uint32_t attrType, - bool enforcePrivate) const -{ - bool localizationSetting = accessor != NULL && accessor->getLocalizationSetting(); - const char* errorMsg = NULL; - - outValue->size = sizeof(Res_value); - outValue->res0 = 0; - - // First strip leading/trailing whitespace. Do this before handling - // escapes, so they can be used to force whitespace into the string. - if (!preserveSpaces) { - while (len > 0 && isspace16(*s)) { - s++; - len--; - } - while (len > 0 && isspace16(s[len-1])) { - len--; - } - // If the string ends with '\', then we keep the space after it. - if (len > 0 && s[len-1] == '\\' && s[len] != 0) { - len++; - } - } - - //printf("Value for: %s\n", String8(s, len).string()); - - uint32_t l10nReq = ResTable_map::L10N_NOT_REQUIRED; - uint32_t attrMin = 0x80000000, attrMax = 0x7fffffff; - bool fromAccessor = false; - if (attrID != 0 && !Res_INTERNALID(attrID)) { - const ssize_t p = getResourcePackageIndex(attrID); - const bag_entry* bag; - ssize_t cnt = p >= 0 ? lockBag(attrID, &bag) : -1; - //printf("For attr 0x%08x got bag of %d\n", attrID, cnt); - if (cnt >= 0) { - while (cnt > 0) { - //printf("Entry 0x%08x = 0x%08x\n", bag->map.name.ident, bag->map.value.data); - switch (bag->map.name.ident) { - case ResTable_map::ATTR_TYPE: - attrType = bag->map.value.data; - break; - case ResTable_map::ATTR_MIN: - attrMin = bag->map.value.data; - break; - case ResTable_map::ATTR_MAX: - attrMax = bag->map.value.data; - break; - case ResTable_map::ATTR_L10N: - l10nReq = bag->map.value.data; - break; - } - bag++; - cnt--; - } - unlockBag(bag); - } else if (accessor && accessor->getAttributeType(attrID, &attrType)) { - fromAccessor = true; - if (attrType == ResTable_map::TYPE_ENUM - || attrType == ResTable_map::TYPE_FLAGS - || attrType == ResTable_map::TYPE_INTEGER) { - accessor->getAttributeMin(attrID, &attrMin); - accessor->getAttributeMax(attrID, &attrMax); - } - if (localizationSetting) { - l10nReq = accessor->getAttributeL10N(attrID); - } - } - } - - const bool canStringCoerce = - coerceType && (attrType&ResTable_map::TYPE_STRING) != 0; - - if (*s == '@') { - outValue->dataType = outValue->TYPE_REFERENCE; - - // Note: we don't check attrType here because the reference can - // be to any other type; we just need to count on the client making - // sure the referenced type is correct. - - //printf("Looking up ref: %s\n", String8(s, len).string()); - - // It's a reference! - if (len == 5 && s[1]=='n' && s[2]=='u' && s[3]=='l' && s[4]=='l') { - outValue->data = 0; - return true; - } else { - bool createIfNotFound = false; - const char16_t* resourceRefName; - int resourceNameLen; - if (len > 2 && s[1] == '+') { - createIfNotFound = true; - resourceRefName = s + 2; - resourceNameLen = len - 2; - } else if (len > 2 && s[1] == '*') { - enforcePrivate = false; - resourceRefName = s + 2; - resourceNameLen = len - 2; - } else { - createIfNotFound = false; - resourceRefName = s + 1; - resourceNameLen = len - 1; - } - String16 package, type, name; - if (!expandResourceRef(resourceRefName,resourceNameLen, &package, &type, &name, - defType, defPackage, &errorMsg)) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, errorMsg); - } - return false; - } - - uint32_t specFlags = 0; - uint32_t rid = identifierForName(name.string(), name.size(), type.string(), - type.size(), package.string(), package.size(), &specFlags); - if (rid != 0) { - if (enforcePrivate) { - if ((specFlags&ResTable_typeSpec::SPEC_PUBLIC) == 0) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Resource is not public."); - } - return false; - } - } - if (!accessor) { - outValue->data = rid; - return true; - } - rid = Res_MAKEID( - accessor->getRemappedPackage(Res_GETPACKAGE(rid)), - Res_GETTYPE(rid), Res_GETENTRY(rid)); - TABLE_NOISY(printf("Incl %s:%s/%s: 0x%08x\n", - String8(package).string(), String8(type).string(), - String8(name).string(), rid)); - outValue->data = rid; - return true; - } - - if (accessor) { - uint32_t rid = accessor->getCustomResourceWithCreation(package, type, name, - createIfNotFound); - if (rid != 0) { - TABLE_NOISY(printf("Pckg %s:%s/%s: 0x%08x\n", - String8(package).string(), String8(type).string(), - String8(name).string(), rid)); - outValue->data = rid; - return true; - } - } - } - - if (accessor != NULL) { - accessor->reportError(accessorCookie, "No resource found that matches the given name"); - } - return false; - } - - // if we got to here, and localization is required and it's not a reference, - // complain and bail. - if (l10nReq == ResTable_map::L10N_SUGGESTED) { - if (localizationSetting) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "This attribute must be localized."); - } - } - } - - if (*s == '#') { - // It's a color! Convert to an integer of the form 0xaarrggbb. - uint32_t color = 0; - bool error = false; - if (len == 4) { - outValue->dataType = outValue->TYPE_INT_COLOR_RGB4; - color |= 0xFF000000; - color |= get_hex(s[1], &error) << 20; - color |= get_hex(s[1], &error) << 16; - color |= get_hex(s[2], &error) << 12; - color |= get_hex(s[2], &error) << 8; - color |= get_hex(s[3], &error) << 4; - color |= get_hex(s[3], &error); - } else if (len == 5) { - outValue->dataType = outValue->TYPE_INT_COLOR_ARGB4; - color |= get_hex(s[1], &error) << 28; - color |= get_hex(s[1], &error) << 24; - color |= get_hex(s[2], &error) << 20; - color |= get_hex(s[2], &error) << 16; - color |= get_hex(s[3], &error) << 12; - color |= get_hex(s[3], &error) << 8; - color |= get_hex(s[4], &error) << 4; - color |= get_hex(s[4], &error); - } else if (len == 7) { - outValue->dataType = outValue->TYPE_INT_COLOR_RGB8; - color |= 0xFF000000; - color |= get_hex(s[1], &error) << 20; - color |= get_hex(s[2], &error) << 16; - color |= get_hex(s[3], &error) << 12; - color |= get_hex(s[4], &error) << 8; - color |= get_hex(s[5], &error) << 4; - color |= get_hex(s[6], &error); - } else if (len == 9) { - outValue->dataType = outValue->TYPE_INT_COLOR_ARGB8; - color |= get_hex(s[1], &error) << 28; - color |= get_hex(s[2], &error) << 24; - color |= get_hex(s[3], &error) << 20; - color |= get_hex(s[4], &error) << 16; - color |= get_hex(s[5], &error) << 12; - color |= get_hex(s[6], &error) << 8; - color |= get_hex(s[7], &error) << 4; - color |= get_hex(s[8], &error); - } else { - error = true; - } - if (!error) { - if ((attrType&ResTable_map::TYPE_COLOR) == 0) { - if (!canStringCoerce) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, - "Color types not allowed"); - } - return false; - } - } else { - outValue->data = color; - //printf("Color input=%s, output=0x%x\n", String8(s, len).string(), color); - return true; - } - } else { - if ((attrType&ResTable_map::TYPE_COLOR) != 0) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Color value not valid --" - " must be #rgb, #argb, #rrggbb, or #aarrggbb"); - } - #if 0 - fprintf(stderr, "%s: Color ID %s value %s is not valid\n", - "Resource File", //(const char*)in->getPrintableSource(), - String8(*curTag).string(), - String8(s, len).string()); - #endif - return false; - } - } - } - - if (*s == '?') { - outValue->dataType = outValue->TYPE_ATTRIBUTE; - - // Note: we don't check attrType here because the reference can - // be to any other type; we just need to count on the client making - // sure the referenced type is correct. - - //printf("Looking up attr: %s\n", String8(s, len).string()); - - static const String16 attr16("attr"); - String16 package, type, name; - if (!expandResourceRef(s+1, len-1, &package, &type, &name, - &attr16, defPackage, &errorMsg)) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, errorMsg); - } - return false; - } - - //printf("Pkg: %s, Type: %s, Name: %s\n", - // String8(package).string(), String8(type).string(), - // String8(name).string()); - uint32_t specFlags = 0; - uint32_t rid = - identifierForName(name.string(), name.size(), - type.string(), type.size(), - package.string(), package.size(), &specFlags); - if (rid != 0) { - if (enforcePrivate) { - if ((specFlags&ResTable_typeSpec::SPEC_PUBLIC) == 0) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Attribute is not public."); - } - return false; - } - } - if (!accessor) { - outValue->data = rid; - return true; - } - rid = Res_MAKEID( - accessor->getRemappedPackage(Res_GETPACKAGE(rid)), - Res_GETTYPE(rid), Res_GETENTRY(rid)); - //printf("Incl %s:%s/%s: 0x%08x\n", - // String8(package).string(), String8(type).string(), - // String8(name).string(), rid); - outValue->data = rid; - return true; - } - - if (accessor) { - uint32_t rid = accessor->getCustomResource(package, type, name); - if (rid != 0) { - //printf("Mine %s:%s/%s: 0x%08x\n", - // String8(package).string(), String8(type).string(), - // String8(name).string(), rid); - outValue->data = rid; - return true; - } - } - - if (accessor != NULL) { - accessor->reportError(accessorCookie, "No resource found that matches the given name"); - } - return false; - } - - if (stringToInt(s, len, outValue)) { - if ((attrType&ResTable_map::TYPE_INTEGER) == 0) { - // If this type does not allow integers, but does allow floats, - // fall through on this error case because the float type should - // be able to accept any integer value. - if (!canStringCoerce && (attrType&ResTable_map::TYPE_FLOAT) == 0) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Integer types not allowed"); - } - return false; - } - } else { - if (((int32_t)outValue->data) < ((int32_t)attrMin) - || ((int32_t)outValue->data) > ((int32_t)attrMax)) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Integer value out of range"); - } - return false; - } - return true; - } - } - - if (stringToFloat(s, len, outValue)) { - if (outValue->dataType == Res_value::TYPE_DIMENSION) { - if ((attrType&ResTable_map::TYPE_DIMENSION) != 0) { - return true; - } - if (!canStringCoerce) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Dimension types not allowed"); - } - return false; - } - } else if (outValue->dataType == Res_value::TYPE_FRACTION) { - if ((attrType&ResTable_map::TYPE_FRACTION) != 0) { - return true; - } - if (!canStringCoerce) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Fraction types not allowed"); - } - return false; - } - } else if ((attrType&ResTable_map::TYPE_FLOAT) == 0) { - if (!canStringCoerce) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Float types not allowed"); - } - return false; - } - } else { - return true; - } - } - - if (len == 4) { - if ((s[0] == 't' || s[0] == 'T') && - (s[1] == 'r' || s[1] == 'R') && - (s[2] == 'u' || s[2] == 'U') && - (s[3] == 'e' || s[3] == 'E')) { - if ((attrType&ResTable_map::TYPE_BOOLEAN) == 0) { - if (!canStringCoerce) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Boolean types not allowed"); - } - return false; - } - } else { - outValue->dataType = outValue->TYPE_INT_BOOLEAN; - outValue->data = (uint32_t)-1; - return true; - } - } - } - - if (len == 5) { - if ((s[0] == 'f' || s[0] == 'F') && - (s[1] == 'a' || s[1] == 'A') && - (s[2] == 'l' || s[2] == 'L') && - (s[3] == 's' || s[3] == 'S') && - (s[4] == 'e' || s[4] == 'E')) { - if ((attrType&ResTable_map::TYPE_BOOLEAN) == 0) { - if (!canStringCoerce) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "Boolean types not allowed"); - } - return false; - } - } else { - outValue->dataType = outValue->TYPE_INT_BOOLEAN; - outValue->data = 0; - return true; - } - } - } - - if ((attrType&ResTable_map::TYPE_ENUM) != 0) { - const ssize_t p = getResourcePackageIndex(attrID); - const bag_entry* bag; - ssize_t cnt = p >= 0 ? lockBag(attrID, &bag) : -1; - //printf("Got %d for enum\n", cnt); - if (cnt >= 0) { - resource_name rname; - while (cnt > 0) { - if (!Res_INTERNALID(bag->map.name.ident)) { - //printf("Trying attr #%08x\n", bag->map.name.ident); - if (getResourceName(bag->map.name.ident, &rname)) { - #if 0 - printf("Matching %s against %s (0x%08x)\n", - String8(s, len).string(), - String8(rname.name, rname.nameLen).string(), - bag->map.name.ident); - #endif - if (strzcmp16(s, len, rname.name, rname.nameLen) == 0) { - outValue->dataType = bag->map.value.dataType; - outValue->data = bag->map.value.data; - unlockBag(bag); - return true; - } - } - - } - bag++; - cnt--; - } - unlockBag(bag); - } - - if (fromAccessor) { - if (accessor->getAttributeEnum(attrID, s, len, outValue)) { - return true; - } - } - } - - if ((attrType&ResTable_map::TYPE_FLAGS) != 0) { - const ssize_t p = getResourcePackageIndex(attrID); - const bag_entry* bag; - ssize_t cnt = p >= 0 ? lockBag(attrID, &bag) : -1; - //printf("Got %d for flags\n", cnt); - if (cnt >= 0) { - bool failed = false; - resource_name rname; - outValue->dataType = Res_value::TYPE_INT_HEX; - outValue->data = 0; - const char16_t* end = s + len; - const char16_t* pos = s; - while (pos < end && !failed) { - const char16_t* start = pos; - end++; - while (pos < end && *pos != '|') { - pos++; - } - //printf("Looking for: %s\n", String8(start, pos-start).string()); - const bag_entry* bagi = bag; - ssize_t i; - for (i=0; i<cnt; i++, bagi++) { - if (!Res_INTERNALID(bagi->map.name.ident)) { - //printf("Trying attr #%08x\n", bagi->map.name.ident); - if (getResourceName(bagi->map.name.ident, &rname)) { - #if 0 - printf("Matching %s against %s (0x%08x)\n", - String8(start,pos-start).string(), - String8(rname.name, rname.nameLen).string(), - bagi->map.name.ident); - #endif - if (strzcmp16(start, pos-start, rname.name, rname.nameLen) == 0) { - outValue->data |= bagi->map.value.data; - break; - } - } - } - } - if (i >= cnt) { - // Didn't find this flag identifier. - failed = true; - } - if (pos < end) { - pos++; - } - } - unlockBag(bag); - if (!failed) { - //printf("Final flag value: 0x%lx\n", outValue->data); - return true; - } - } - - - if (fromAccessor) { - if (accessor->getAttributeFlags(attrID, s, len, outValue)) { - //printf("Final flag value: 0x%lx\n", outValue->data); - return true; - } - } - } - - if ((attrType&ResTable_map::TYPE_STRING) == 0) { - if (accessor != NULL) { - accessor->reportError(accessorCookie, "String types not allowed"); - } - return false; - } - - // Generic string handling... - outValue->dataType = outValue->TYPE_STRING; - if (outString) { - bool failed = collectString(outString, s, len, preserveSpaces, &errorMsg); - if (accessor != NULL) { - accessor->reportError(accessorCookie, errorMsg); - } - return failed; - } - - return true; -} - -bool ResTable::collectString(String16* outString, - const char16_t* s, size_t len, - bool preserveSpaces, - const char** outErrorMsg, - bool append) -{ - String16 tmp; - - char quoted = 0; - const char16_t* p = s; - while (p < (s+len)) { - while (p < (s+len)) { - const char16_t c = *p; - if (c == '\\') { - break; - } - if (!preserveSpaces) { - if (quoted == 0 && isspace16(c) - && (c != ' ' || isspace16(*(p+1)))) { - break; - } - if (c == '"' && (quoted == 0 || quoted == '"')) { - break; - } - if (c == '\'' && (quoted == 0 || quoted == '\'')) { - break; - } - } - p++; - } - if (p < (s+len)) { - if (p > s) { - tmp.append(String16(s, p-s)); - } - if (!preserveSpaces && (*p == '"' || *p == '\'')) { - if (quoted == 0) { - quoted = *p; - } else { - quoted = 0; - } - p++; - } else if (!preserveSpaces && isspace16(*p)) { - // Space outside of a quote -- consume all spaces and - // leave a single plain space char. - tmp.append(String16(" ")); - p++; - while (p < (s+len) && isspace16(*p)) { - p++; - } - } else if (*p == '\\') { - p++; - if (p < (s+len)) { - switch (*p) { - case 't': - tmp.append(String16("\t")); - break; - case 'n': - tmp.append(String16("\n")); - break; - case '#': - tmp.append(String16("#")); - break; - case '@': - tmp.append(String16("@")); - break; - case '?': - tmp.append(String16("?")); - break; - case '"': - tmp.append(String16("\"")); - break; - case '\'': - tmp.append(String16("'")); - break; - case '\\': - tmp.append(String16("\\")); - break; - case 'u': - { - char16_t chr = 0; - int i = 0; - while (i < 4 && p[1] != 0) { - p++; - i++; - int c; - if (*p >= '0' && *p <= '9') { - c = *p - '0'; - } else if (*p >= 'a' && *p <= 'f') { - c = *p - 'a' + 10; - } else if (*p >= 'A' && *p <= 'F') { - c = *p - 'A' + 10; - } else { - if (outErrorMsg) { - *outErrorMsg = "Bad character in \\u unicode escape sequence"; - } - return false; - } - chr = (chr<<4) | c; - } - tmp.append(String16(&chr, 1)); - } break; - default: - // ignore unknown escape chars. - break; - } - p++; - } - } - len -= (p-s); - s = p; - } - } - - if (tmp.size() != 0) { - if (len > 0) { - tmp.append(String16(s, len)); - } - if (append) { - outString->append(tmp); - } else { - outString->setTo(tmp); - } - } else { - if (append) { - outString->append(String16(s, len)); - } else { - outString->setTo(s, len); - } - } - - return true; -} - -size_t ResTable::getBasePackageCount() const -{ - if (mError != NO_ERROR) { - return 0; - } - return mPackageGroups.size(); -} - -const char16_t* ResTable::getBasePackageName(size_t idx) const -{ - if (mError != NO_ERROR) { - return 0; - } - LOG_FATAL_IF(idx >= mPackageGroups.size(), - "Requested package index %d past package count %d", - (int)idx, (int)mPackageGroups.size()); - return mPackageGroups[idx]->name.string(); -} - -uint32_t ResTable::getBasePackageId(size_t idx) const -{ - if (mError != NO_ERROR) { - return 0; - } - LOG_FATAL_IF(idx >= mPackageGroups.size(), - "Requested package index %d past package count %d", - (int)idx, (int)mPackageGroups.size()); - return mPackageGroups[idx]->id; -} - -size_t ResTable::getTableCount() const -{ - return mHeaders.size(); -} - -const ResStringPool* ResTable::getTableStringBlock(size_t index) const -{ - return &mHeaders[index]->values; -} - -void* ResTable::getTableCookie(size_t index) const -{ - return mHeaders[index]->cookie; -} - -void ResTable::getConfigurations(Vector<ResTable_config>* configs) const -{ - const size_t I = mPackageGroups.size(); - for (size_t i=0; i<I; i++) { - const PackageGroup* packageGroup = mPackageGroups[i]; - const size_t J = packageGroup->packages.size(); - for (size_t j=0; j<J; j++) { - const Package* package = packageGroup->packages[j]; - const size_t K = package->types.size(); - for (size_t k=0; k<K; k++) { - const Type* type = package->types[k]; - if (type == NULL) continue; - const size_t L = type->configs.size(); - for (size_t l=0; l<L; l++) { - const ResTable_type* config = type->configs[l]; - const ResTable_config* cfg = &config->config; - // only insert unique - const size_t M = configs->size(); - size_t m; - for (m=0; m<M; m++) { - if (0 == (*configs)[m].compare(*cfg)) { - break; - } - } - // if we didn't find it - if (m == M) { - configs->add(*cfg); - } - } - } - } - } -} - -void ResTable::getLocales(Vector<String8>* locales) const -{ - Vector<ResTable_config> configs; - LOGD("calling getConfigurations"); - getConfigurations(&configs); - LOGD("called getConfigurations size=%d", (int)configs.size()); - const size_t I = configs.size(); - for (size_t i=0; i<I; i++) { - char locale[6]; - configs[i].getLocale(locale); - const size_t J = locales->size(); - size_t j; - for (j=0; j<J; j++) { - if (0 == strcmp(locale, (*locales)[j].string())) { - break; - } - } - if (j == J) { - locales->add(String8(locale)); - } - } -} - -ssize_t ResTable::getEntry( - const Package* package, int typeIndex, int entryIndex, - const ResTable_config* config, - const ResTable_type** outType, const ResTable_entry** outEntry, - const Type** outTypeClass) const -{ - LOGV("Getting entry from package %p\n", package); - const ResTable_package* const pkg = package->package; - - const Type* allTypes = package->getType(typeIndex); - LOGV("allTypes=%p\n", allTypes); - if (allTypes == NULL) { - LOGV("Skipping entry type index 0x%02x because type is NULL!\n", typeIndex); - return 0; - } - - if ((size_t)entryIndex >= allTypes->entryCount) { - LOGW("getEntry failing because entryIndex %d is beyond type entryCount %d", - entryIndex, (int)allTypes->entryCount); - return BAD_TYPE; - } - - const ResTable_type* type = NULL; - uint32_t offset = ResTable_type::NO_ENTRY; - ResTable_config bestConfig; - memset(&bestConfig, 0, sizeof(bestConfig)); // make the compiler shut up - - const size_t NT = allTypes->configs.size(); - for (size_t i=0; i<NT; i++) { - const ResTable_type* const thisType = allTypes->configs[i]; - if (thisType == NULL) continue; - - ResTable_config thisConfig; - thisConfig.copyFromDtoH(thisType->config); - - TABLE_GETENTRY(LOGI("Match entry 0x%x in type 0x%x (sz 0x%x): imsi:%d/%d=%d/%d lang:%c%c=%c%c cnt:%c%c=%c%c " - "orien:%d=%d touch:%d=%d density:%d=%d key:%d=%d inp:%d=%d nav:%d=%d w:%d=%d h:%d=%d\n", - entryIndex, typeIndex+1, dtohl(thisType->config.size), - thisConfig.mcc, thisConfig.mnc, - config ? config->mcc : 0, config ? config->mnc : 0, - thisConfig.language[0] ? thisConfig.language[0] : '-', - thisConfig.language[1] ? thisConfig.language[1] : '-', - config && config->language[0] ? config->language[0] : '-', - config && config->language[1] ? config->language[1] : '-', - thisConfig.country[0] ? thisConfig.country[0] : '-', - thisConfig.country[1] ? thisConfig.country[1] : '-', - config && config->country[0] ? config->country[0] : '-', - config && config->country[1] ? config->country[1] : '-', - thisConfig.orientation, - config ? config->orientation : 0, - thisConfig.touchscreen, - config ? config->touchscreen : 0, - thisConfig.density, - config ? config->density : 0, - thisConfig.keyboard, - config ? config->keyboard : 0, - thisConfig.inputFlags, - config ? config->inputFlags : 0, - thisConfig.navigation, - config ? config->navigation : 0, - thisConfig.screenWidth, - config ? config->screenWidth : 0, - thisConfig.screenHeight, - config ? config->screenHeight : 0)); - - // Check to make sure this one is valid for the current parameters. - if (config && !thisConfig.match(*config)) { - TABLE_GETENTRY(LOGI("Does not match config!\n")); - continue; - } - - // Check if there is the desired entry in this type. - - const uint8_t* const end = ((const uint8_t*)thisType) - + dtohl(thisType->header.size); - const uint32_t* const eindex = (const uint32_t*) - (((const uint8_t*)thisType) + dtohs(thisType->header.headerSize)); - - uint32_t thisOffset = dtohl(eindex[entryIndex]); - if (thisOffset == ResTable_type::NO_ENTRY) { - TABLE_GETENTRY(LOGI("Skipping because it is not defined!\n")); - continue; - } - - if (type != NULL) { - // Check if this one is less specific than the last found. If so, - // we will skip it. We check starting with things we most care - // about to those we least care about. - if (!thisConfig.isBetterThan(bestConfig, config)) { - TABLE_GETENTRY(LOGI("This config is worse than last!\n")); - continue; - } - } - - type = thisType; - offset = thisOffset; - bestConfig = thisConfig; - TABLE_GETENTRY(LOGI("Best entry so far -- using it!\n")); - if (!config) break; - } - - if (type == NULL) { - TABLE_GETENTRY(LOGI("No value found for requested entry!\n")); - return BAD_INDEX; - } - - offset += dtohl(type->entriesStart); - TABLE_NOISY(aout << "Looking in resource table " << package->header->header - << ", typeOff=" - << (void*)(((const char*)type)-((const char*)package->header->header)) - << ", offset=" << (void*)offset << endl); - - if (offset > (dtohl(type->header.size)-sizeof(ResTable_entry))) { - LOGW("ResTable_entry at 0x%x is beyond type chunk data 0x%x", - offset, dtohl(type->header.size)); - return BAD_TYPE; - } - if ((offset&0x3) != 0) { - LOGW("ResTable_entry at 0x%x is not on an integer boundary", - offset); - return BAD_TYPE; - } - - const ResTable_entry* const entry = (const ResTable_entry*) - (((const uint8_t*)type) + offset); - if (dtohs(entry->size) < sizeof(*entry)) { - LOGW("ResTable_entry size 0x%x is too small", dtohs(entry->size)); - return BAD_TYPE; - } - - *outType = type; - *outEntry = entry; - if (outTypeClass != NULL) { - *outTypeClass = allTypes; - } - return offset + dtohs(entry->size); -} - -status_t ResTable::parsePackage(const ResTable_package* const pkg, - const Header* const header) -{ - const uint8_t* base = (const uint8_t*)pkg; - status_t err = validate_chunk(&pkg->header, sizeof(*pkg), - header->dataEnd, "ResTable_package"); - if (err != NO_ERROR) { - return (mError=err); - } - - const size_t pkgSize = dtohl(pkg->header.size); - - if (dtohl(pkg->typeStrings) >= pkgSize) { - LOGW("ResTable_package type strings at %p are past chunk size %p.", - (void*)dtohl(pkg->typeStrings), (void*)pkgSize); - return (mError=BAD_TYPE); - } - if ((dtohl(pkg->typeStrings)&0x3) != 0) { - LOGW("ResTable_package type strings at %p is not on an integer boundary.", - (void*)dtohl(pkg->typeStrings)); - return (mError=BAD_TYPE); - } - if (dtohl(pkg->keyStrings) >= pkgSize) { - LOGW("ResTable_package key strings at %p are past chunk size %p.", - (void*)dtohl(pkg->keyStrings), (void*)pkgSize); - return (mError=BAD_TYPE); - } - if ((dtohl(pkg->keyStrings)&0x3) != 0) { - LOGW("ResTable_package key strings at %p is not on an integer boundary.", - (void*)dtohl(pkg->keyStrings)); - return (mError=BAD_TYPE); - } - - Package* package = NULL; - PackageGroup* group = NULL; - uint32_t id = dtohl(pkg->id); - if (id != 0 && id < 256) { - size_t idx = mPackageMap[id]; - if (idx == 0) { - idx = mPackageGroups.size()+1; - - char16_t tmpName[sizeof(pkg->name)/sizeof(char16_t)]; - strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(char16_t)); - group = new PackageGroup(String16(tmpName), id); - if (group == NULL) { - return (mError=NO_MEMORY); - } - - err = group->typeStrings.setTo(base+dtohl(pkg->typeStrings), - header->dataEnd-(base+dtohl(pkg->typeStrings))); - if (err != NO_ERROR) { - return (mError=err); - } - err = group->keyStrings.setTo(base+dtohl(pkg->keyStrings), - header->dataEnd-(base+dtohl(pkg->keyStrings))); - if (err != NO_ERROR) { - return (mError=err); - } - - //printf("Adding new package id %d at index %d\n", id, idx); - err = mPackageGroups.add(group); - if (err < NO_ERROR) { - return (mError=err); - } - mPackageMap[id] = (uint8_t)idx; - } else { - group = mPackageGroups.itemAt(idx-1); - if (group == NULL) { - return (mError=UNKNOWN_ERROR); - } - } - package = new Package(header, pkg); - if (package == NULL) { - return (mError=NO_MEMORY); - } - err = group->packages.add(package); - if (err < NO_ERROR) { - return (mError=err); - } - } else { - LOG_ALWAYS_FATAL("Skins not supported!"); - return NO_ERROR; - } - - - // Iterate through all chunks. - size_t curPackage = 0; - - const ResChunk_header* chunk = - (const ResChunk_header*)(((const uint8_t*)pkg) - + dtohs(pkg->header.headerSize)); - const uint8_t* endPos = ((const uint8_t*)pkg) + dtohs(pkg->header.size); - while (((const uint8_t*)chunk) <= (endPos-sizeof(ResChunk_header)) && - ((const uint8_t*)chunk) <= (endPos-dtohl(chunk->size))) { - TABLE_NOISY(LOGV("PackageChunk: type=0x%x, headerSize=0x%x, size=0x%x, pos=%p\n", - dtohs(chunk->type), dtohs(chunk->headerSize), dtohl(chunk->size), - (void*)(((const uint8_t*)chunk) - ((const uint8_t*)header->header)))); - const size_t csize = dtohl(chunk->size); - const uint16_t ctype = dtohs(chunk->type); - if (ctype == RES_TABLE_TYPE_SPEC_TYPE) { - const ResTable_typeSpec* typeSpec = (const ResTable_typeSpec*)(chunk); - err = validate_chunk(&typeSpec->header, sizeof(*typeSpec), - endPos, "ResTable_typeSpec"); - if (err != NO_ERROR) { - return (mError=err); - } - - const size_t typeSpecSize = dtohl(typeSpec->header.size); - - LOAD_TABLE_NOISY(printf("TypeSpec off %p: type=0x%x, headerSize=0x%x, size=%p\n", - (void*)(base-(const uint8_t*)chunk), - dtohs(typeSpec->header.type), - dtohs(typeSpec->header.headerSize), - (void*)typeSize)); - // look for block overrun or int overflow when multiplying by 4 - if ((dtohl(typeSpec->entryCount) > (INT32_MAX/sizeof(uint32_t)) - || dtohs(typeSpec->header.headerSize)+(sizeof(uint32_t)*dtohl(typeSpec->entryCount)) - > typeSpecSize)) { - LOGW("ResTable_typeSpec entry index to %p extends beyond chunk end %p.", - (void*)(dtohs(typeSpec->header.headerSize) - +(sizeof(uint32_t)*dtohl(typeSpec->entryCount))), - (void*)typeSpecSize); - return (mError=BAD_TYPE); - } - - if (typeSpec->id == 0) { - LOGW("ResTable_type has an id of 0."); - return (mError=BAD_TYPE); - } - - while (package->types.size() < typeSpec->id) { - package->types.add(NULL); - } - Type* t = package->types[typeSpec->id-1]; - if (t == NULL) { - t = new Type(header, package, dtohl(typeSpec->entryCount)); - package->types.editItemAt(typeSpec->id-1) = t; - } else if (dtohl(typeSpec->entryCount) != t->entryCount) { - LOGW("ResTable_typeSpec entry count inconsistent: given %d, previously %d", - (int)dtohl(typeSpec->entryCount), (int)t->entryCount); - return (mError=BAD_TYPE); - } - t->typeSpecFlags = (const uint32_t*)( - ((const uint8_t*)typeSpec) + dtohs(typeSpec->header.headerSize)); - t->typeSpec = typeSpec; - - } else if (ctype == RES_TABLE_TYPE_TYPE) { - const ResTable_type* type = (const ResTable_type*)(chunk); - err = validate_chunk(&type->header, sizeof(*type)-sizeof(ResTable_config)+4, - endPos, "ResTable_type"); - if (err != NO_ERROR) { - return (mError=err); - } - - const size_t typeSize = dtohl(type->header.size); - - LOAD_TABLE_NOISY(printf("Type off %p: type=0x%x, headerSize=0x%x, size=%p\n", - (void*)(base-(const uint8_t*)chunk), - dtohs(type->header.type), - dtohs(type->header.headerSize), - (void*)typeSize)); - if (dtohs(type->header.headerSize)+(sizeof(uint32_t)*dtohl(type->entryCount)) - > typeSize) { - LOGW("ResTable_type entry index to %p extends beyond chunk end %p.", - (void*)(dtohs(type->header.headerSize) - +(sizeof(uint32_t)*dtohl(type->entryCount))), - (void*)typeSize); - return (mError=BAD_TYPE); - } - if (dtohl(type->entryCount) != 0 - && dtohl(type->entriesStart) > (typeSize-sizeof(ResTable_entry))) { - LOGW("ResTable_type entriesStart at %p extends beyond chunk end %p.", - (void*)dtohl(type->entriesStart), (void*)typeSize); - return (mError=BAD_TYPE); - } - if (type->id == 0) { - LOGW("ResTable_type has an id of 0."); - return (mError=BAD_TYPE); - } - - while (package->types.size() < type->id) { - package->types.add(NULL); - } - Type* t = package->types[type->id-1]; - if (t == NULL) { - t = new Type(header, package, dtohl(type->entryCount)); - package->types.editItemAt(type->id-1) = t; - } else if (dtohl(type->entryCount) != t->entryCount) { - LOGW("ResTable_type entry count inconsistent: given %d, previously %d", - (int)dtohl(type->entryCount), (int)t->entryCount); - return (mError=BAD_TYPE); - } - - TABLE_GETENTRY( - ResTable_config thisConfig; - thisConfig.copyFromDtoH(type->config); - LOGI("Adding config to type %d: imsi:%d/%d lang:%c%c cnt:%c%c " - "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n", - type->id, - thisConfig.mcc, thisConfig.mnc, - thisConfig.language[0] ? thisConfig.language[0] : '-', - thisConfig.language[1] ? thisConfig.language[1] : '-', - thisConfig.country[0] ? thisConfig.country[0] : '-', - thisConfig.country[1] ? thisConfig.country[1] : '-', - thisConfig.orientation, - thisConfig.touchscreen, - thisConfig.density, - thisConfig.keyboard, - thisConfig.inputFlags, - thisConfig.navigation, - thisConfig.screenWidth, - thisConfig.screenHeight)); - t->configs.add(type); - } else { - status_t err = validate_chunk(chunk, sizeof(ResChunk_header), - endPos, "ResTable_package:unknown"); - if (err != NO_ERROR) { - return (mError=err); - } - } - chunk = (const ResChunk_header*) - (((const uint8_t*)chunk) + csize); - } - - if (group->typeCount == 0) { - group->typeCount = package->types.size(); - } - - return NO_ERROR; -} - -#ifndef HAVE_ANDROID_OS -#define CHAR16_TO_CSTR(c16, len) (String8(String16(c16,len)).string()) - -#define CHAR16_ARRAY_EQ(constant, var, len) \ - ((len == (sizeof(constant)/sizeof(constant[0]))) && (0 == memcmp((var), (constant), (len)))) - -void ResTable::print() const -{ - printf("mError=0x%x (%s)\n", mError, strerror(mError)); -#if 0 - printf("mParams=%c%c-%c%c,\n", - mParams.language[0], mParams.language[1], - mParams.country[0], mParams.country[1]); -#endif - size_t pgCount = mPackageGroups.size(); - printf("Package Groups (%d)\n", (int)pgCount); - for (size_t pgIndex=0; pgIndex<pgCount; pgIndex++) { - const PackageGroup* pg = mPackageGroups[pgIndex]; - printf("Package Group %d id=%d packageCount=%d name=%s\n", - (int)pgIndex, pg->id, (int)pg->packages.size(), - String8(pg->name).string()); - - size_t pkgCount = pg->packages.size(); - for (size_t pkgIndex=0; pkgIndex<pkgCount; pkgIndex++) { - const Package* pkg = pg->packages[pkgIndex]; - size_t typeCount = pkg->types.size(); - printf(" Package %d id=%d name=%s typeCount=%d\n", (int)pkgIndex, - pkg->package->id, String8(String16(pkg->package->name)).string(), - (int)typeCount); - for (size_t typeIndex=0; typeIndex<typeCount; typeIndex++) { - const Type* typeConfigs = pkg->getType(typeIndex); - if (typeConfigs == NULL) { - printf(" type %d NULL\n", (int)typeIndex); - continue; - } - const size_t NTC = typeConfigs->configs.size(); - printf(" type %d configCount=%d entryCount=%d\n", - (int)typeIndex, (int)NTC, (int)typeConfigs->entryCount); - if (typeConfigs->typeSpecFlags != NULL) { - for (size_t entryIndex=0; entryIndex<typeConfigs->entryCount; entryIndex++) { - uint32_t resID = (0xff000000 & ((pkg->package->id)<<24)) - | (0x00ff0000 & ((typeIndex+1)<<16)) - | (0x0000ffff & (entryIndex)); - resource_name resName; - this->getResourceName(resID, &resName); - printf(" spec resource 0x%08x %s:%s/%s: flags=0x%08x\n", - resID, - CHAR16_TO_CSTR(resName.package, resName.packageLen), - CHAR16_TO_CSTR(resName.type, resName.typeLen), - CHAR16_TO_CSTR(resName.name, resName.nameLen), - dtohl(typeConfigs->typeSpecFlags[entryIndex])); - } - } - for (size_t configIndex=0; configIndex<NTC; configIndex++) { - const ResTable_type* type = typeConfigs->configs[configIndex]; - if ((((uint64_t)type)&0x3) != 0) { - printf(" NON-INTEGER ResTable_type ADDRESS: %p\n", type); - continue; - } - printf(" config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%d key=%d infl=%d nav=%d w=%d h=%d\n", - (int)configIndex, - type->config.language[0] ? type->config.language[0] : '-', - type->config.language[1] ? type->config.language[1] : '-', - type->config.country[0] ? type->config.country[0] : '-', - type->config.country[1] ? type->config.country[1] : '-', - type->config.orientation, - type->config.touchscreen, - dtohs(type->config.density), - type->config.keyboard, - type->config.inputFlags, - type->config.navigation, - dtohs(type->config.screenWidth), - dtohs(type->config.screenHeight)); - size_t entryCount = dtohl(type->entryCount); - uint32_t entriesStart = dtohl(type->entriesStart); - if ((entriesStart&0x3) != 0) { - printf(" NON-INTEGER ResTable_type entriesStart OFFSET: %p\n", (void*)entriesStart); - continue; - } - uint32_t typeSize = dtohl(type->header.size); - if ((typeSize&0x3) != 0) { - printf(" NON-INTEGER ResTable_type header.size: %p\n", (void*)typeSize); - continue; - } - for (size_t entryIndex=0; entryIndex<entryCount; entryIndex++) { - - const uint8_t* const end = ((const uint8_t*)type) - + dtohl(type->header.size); - const uint32_t* const eindex = (const uint32_t*) - (((const uint8_t*)type) + dtohs(type->header.headerSize)); - - uint32_t thisOffset = dtohl(eindex[entryIndex]); - if (thisOffset == ResTable_type::NO_ENTRY) { - continue; - } - - uint32_t resID = (0xff000000 & ((pkg->package->id)<<24)) - | (0x00ff0000 & ((typeIndex+1)<<16)) - | (0x0000ffff & (entryIndex)); - resource_name resName; - this->getResourceName(resID, &resName); - printf(" resource 0x%08x %s:%s/%s: ", resID, - CHAR16_TO_CSTR(resName.package, resName.packageLen), - CHAR16_TO_CSTR(resName.type, resName.typeLen), - CHAR16_TO_CSTR(resName.name, resName.nameLen)); - if ((thisOffset&0x3) != 0) { - printf("NON-INTEGER OFFSET: %p\n", (void*)thisOffset); - continue; - } - if ((thisOffset+sizeof(ResTable_entry)) > typeSize) { - printf("OFFSET OUT OF BOUNDS: %p+%p (size is %p)\n", - (void*)entriesStart, (void*)thisOffset, - (void*)typeSize); - continue; - } - - const ResTable_entry* ent = (const ResTable_entry*) - (((const uint8_t*)type) + entriesStart + thisOffset); - if (((entriesStart + thisOffset)&0x3) != 0) { - printf("NON-INTEGER ResTable_entry OFFSET: %p\n", - (void*)(entriesStart + thisOffset)); - continue; - } - if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) { - printf("<bag>"); - } else { - uint16_t esize = dtohs(ent->size); - if ((esize&0x3) != 0) { - printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize); - continue; - } - if ((thisOffset+esize) > typeSize) { - printf("ResTable_entry OUT OF BOUNDS: %p+%p+%p (size is %p)\n", - (void*)entriesStart, (void*)thisOffset, - (void*)esize, (void*)typeSize); - continue; - } - - const Res_value* value = (const Res_value*) - (((const uint8_t*)ent) + esize); - printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)", - (int)value->dataType, (int)dtohl(value->data), - (int)dtohs(value->size), (int)value->res0); - } - - if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) { - printf(" (PUBLIC)"); - } - printf("\n"); - } - } - } - } - } -} - -#endif // HAVE_ANDROID_OS - -} // namespace android diff --git a/libs/utils/SharedBuffer.cpp b/libs/utils/SharedBuffer.cpp deleted file mode 100644 index 3555fb7..0000000 --- a/libs/utils/SharedBuffer.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdlib.h> -#include <string.h> - -#include <utils/SharedBuffer.h> -#include <utils/Atomic.h> - -// --------------------------------------------------------------------------- - -namespace android { - -SharedBuffer* SharedBuffer::alloc(size_t size) -{ - SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size)); - if (sb) { - sb->mRefs = 1; - sb->mSize = size; - } - return sb; -} - - -ssize_t SharedBuffer::dealloc(const SharedBuffer* released) -{ - if (released->mRefs != 0) return -1; // XXX: invalid operation - free(const_cast<SharedBuffer*>(released)); - return 0; -} - -SharedBuffer* SharedBuffer::edit() const -{ - if (onlyOwner()) { - return const_cast<SharedBuffer*>(this); - } - SharedBuffer* sb = alloc(mSize); - if (sb) { - memcpy(sb->data(), data(), size()); - release(); - } - return sb; -} - -SharedBuffer* SharedBuffer::editResize(size_t newSize) const -{ - if (onlyOwner()) { - SharedBuffer* buf = const_cast<SharedBuffer*>(this); - if (buf->mSize == newSize) return buf; - buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize); - if (buf != NULL) { - buf->mSize = newSize; - return buf; - } - } - SharedBuffer* sb = alloc(newSize); - if (sb) { - const size_t mySize = mSize; - memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize); - release(); - } - return sb; -} - -SharedBuffer* SharedBuffer::attemptEdit() const -{ - if (onlyOwner()) { - return const_cast<SharedBuffer*>(this); - } - return 0; -} - -SharedBuffer* SharedBuffer::reset(size_t new_size) const -{ - // cheap-o-reset. - SharedBuffer* sb = alloc(new_size); - if (sb) { - release(); - } - return sb; -} - -void SharedBuffer::acquire() const { - android_atomic_inc(&mRefs); -} - -int32_t SharedBuffer::release(uint32_t flags) const -{ - int32_t prev = 1; - if (onlyOwner() || ((prev = android_atomic_dec(&mRefs)) == 1)) { - mRefs = 0; - if ((flags & eKeepStorage) == 0) { - free(const_cast<SharedBuffer*>(this)); - } - } - return prev; -} - - -}; // namespace android diff --git a/libs/utils/Socket.cpp b/libs/utils/Socket.cpp deleted file mode 100644 index 51509a3..0000000 --- a/libs/utils/Socket.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Internet address class. -// - -#ifdef HAVE_WINSOCK -// This needs to come first, or Cygwin gets concerned about a potential -// clash between WinSock and <sys/types.h>. -# include <winsock2.h> -#endif - -#include <utils/Socket.h> -#include <utils/inet_address.h> -#include <utils/Log.h> -#include <utils/Timers.h> - -#ifndef HAVE_WINSOCK -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <arpa/inet.h> -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - - -/* - * =========================================================================== - * Socket - * =========================================================================== - */ - -#ifndef INVALID_SOCKET -# define INVALID_SOCKET (-1) -#endif -#define UNDEF_SOCKET ((unsigned long) INVALID_SOCKET) - -/*static*/ bool Socket::mBootInitialized = false; - -/* - * Extract system-dependent error code. - */ -static inline int getSocketError(void) { -#ifdef HAVE_WINSOCK - return WSAGetLastError(); -#else - return errno; -#endif -} - -/* - * One-time initialization for socket code. - */ -/*static*/ bool Socket::bootInit(void) -{ -#ifdef HAVE_WINSOCK - WSADATA wsaData; - int err; - - err = WSAStartup(MAKEWORD(2, 0), &wsaData); - if (err != 0) { - LOG(LOG_ERROR, "socket", "Unable to start WinSock\n"); - return false; - } - - LOG(LOG_INFO, "socket", "Using WinSock v%d.%d\n", - LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion)); -#endif - - mBootInitialized = true; - return true; -} - -/* - * One-time shutdown for socket code. - */ -/*static*/ void Socket::finalShutdown(void) -{ -#ifdef HAVE_WINSOCK - WSACleanup(); -#endif - mBootInitialized = false; -} - - -/* - * Simple constructor. Allow the application to create us and then make - * bind/connect calls. - */ -Socket::Socket(void) - : mSock(UNDEF_SOCKET) -{ - if (!mBootInitialized) - LOG(LOG_WARN, "socket", "WARNING: sockets not initialized\n"); -} - -/* - * Destructor. Closes the socket and resets our storage. - */ -Socket::~Socket(void) -{ - close(); -} - - -/* - * Create a socket and connect to the specified host and port. - */ -int Socket::connect(const char* host, int port) -{ - if (mSock != UNDEF_SOCKET) { - LOG(LOG_WARN, "socket", "Socket already connected\n"); - return -1; - } - - InetSocketAddress sockAddr; - if (!sockAddr.create(host, port)) - return -1; - - //return doConnect(sockAddr); - int foo; - foo = doConnect(sockAddr); - return foo; -} - -/* - * Create a socket and connect to the specified host and port. - */ -int Socket::connect(const InetAddress* addr, int port) -{ - if (mSock != UNDEF_SOCKET) { - LOG(LOG_WARN, "socket", "Socket already connected\n"); - return -1; - } - - InetSocketAddress sockAddr; - if (!sockAddr.create(addr, port)) - return -1; - - return doConnect(sockAddr); -} - -/* - * Finish creating a socket by connecting to the remote host. - * - * Returns 0 on success. - */ -int Socket::doConnect(const InetSocketAddress& sockAddr) -{ -#ifdef HAVE_WINSOCK - SOCKET sock; -#else - int sock; -#endif - const InetAddress* addr = sockAddr.getAddress(); - int port = sockAddr.getPort(); - struct sockaddr_in inaddr; - DurationTimer connectTimer; - - assert(sizeof(struct sockaddr_in) == addr->getAddressLength()); - memcpy(&inaddr, addr->getAddress(), addr->getAddressLength()); - inaddr.sin_port = htons(port); - - //fprintf(stderr, "--- connecting to %s:%d\n", - // sockAddr.getHostName(), port); - - sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock == INVALID_SOCKET) { - int err = getSocketError(); - LOG(LOG_ERROR, "socket", "Unable to create socket (err=%d)\n", err); - return (err != 0) ? err : -1; - } - - connectTimer.start(); - - if (::connect(sock, (struct sockaddr*) &inaddr, sizeof(inaddr)) != 0) { - int err = getSocketError(); - LOG(LOG_WARN, "socket", "Connect to %s:%d failed: %d\n", - sockAddr.getHostName(), port, err); - return (err != 0) ? err : -1; - } - - connectTimer.stop(); - if ((long) connectTimer.durationUsecs() > 100000) { - LOG(LOG_INFO, "socket", - "Connect to %s:%d took %.3fs\n", sockAddr.getHostName(), - port, ((long) connectTimer.durationUsecs()) / 1000000.0); - } - - mSock = (unsigned long) sock; - LOG(LOG_VERBOSE, "socket", - "--- connected to %s:%d\n", sockAddr.getHostName(), port); - return 0; -} - - -/* - * Close the socket if it needs closing. - */ -bool Socket::close(void) -{ - if (mSock != UNDEF_SOCKET) { - //fprintf(stderr, "--- closing socket %lu\n", mSock); -#ifdef HAVE_WINSOCK - if (::closesocket((SOCKET) mSock) != 0) - return false; -#else - if (::close((int) mSock) != 0) - return false; -#endif - } - - mSock = UNDEF_SOCKET; - - return true; -} - -/* - * Read data from socket. - * - * Standard semantics: read up to "len" bytes into "buf". Returns the - * number of bytes read, or less than zero on error. - */ -int Socket::read(void* buf, ssize_t len) const -{ - if (mSock == UNDEF_SOCKET) { - LOG(LOG_ERROR, "socket", "ERROR: read on invalid socket\n"); - return -500; - } - -#ifdef HAVE_WINSOCK - SOCKET sock = (SOCKET) mSock; -#else - int sock = (int) mSock; -#endif - int cc; - - cc = recv(sock, (char*)buf, len, 0); - if (cc < 0) { - int err = getSocketError(); - return (err > 0) ? -err : -1; - } - - return cc; -} - -/* - * Write data to a socket. - * - * Standard semantics: write up to "len" bytes into "buf". Returns the - * number of bytes written, or less than zero on error. - */ -int Socket::write(const void* buf, ssize_t len) const -{ - if (mSock == UNDEF_SOCKET) { - LOG(LOG_ERROR, "socket", "ERROR: write on invalid socket\n"); - return -500; - } - -#ifdef HAVE_WINSOCK - SOCKET sock = (SOCKET) mSock; -#else - int sock = (int) mSock; -#endif - int cc; - - cc = send(sock, (const char*)buf, len, 0); - if (cc < 0) { - int err = getSocketError(); - return (err > 0) ? -err : -1; - } - - return cc; -} - - -/* - * =========================================================================== - * Socket tests - * =========================================================================== - */ - -/* - * Read all data from the socket. The data is read into a buffer that - * expands as needed. - * - * On exit, the buffer is returned, and the length of the data is stored - * in "*sz". A null byte is added to the end, but is not included in - * the length. - */ -static char* socketReadAll(const Socket& s, int *sz) -{ - int max, r; - char *data, *ptr, *tmp; - - data = (char*) malloc(max = 32768); - if (data == NULL) - return NULL; - - ptr = data; - - for (;;) { - if ((ptr - data) == max) { - tmp = (char*) realloc(data, max *= 2); - if(tmp == 0) { - free(data); - return 0; - } - } - r = s.read(ptr, max - (ptr - data)); - if (r == 0) - break; - if (r < 0) { - LOG(LOG_WARN, "socket", "WARNING: socket read failed (res=%d)\n",r); - break; - } - ptr += r; - } - - if ((ptr - data) == max) { - tmp = (char*) realloc(data, max + 1); - if (tmp == NULL) { - free(data); - return NULL; - } - } - *ptr = '\0'; - *sz = (ptr - data); - return data; -} - -/* - * Exercise the Socket class. - */ -void android::TestSockets(void) -{ - printf("----- SOCKET TEST ------\n"); - Socket::bootInit(); - - char* buf = NULL; - int len, cc; - const char* kTestStr = - "GET / HTTP/1.0\n" - "Connection: close\n" - "\n"; - - Socket sock; - if (sock.connect("www.google.com", 80) != 0) { - fprintf(stderr, "socket connected failed\n"); - goto bail; - } - - cc = sock.write(kTestStr, strlen(kTestStr)); - if (cc != (int) strlen(kTestStr)) { - fprintf(stderr, "write failed, res=%d\n", cc); - goto bail; - } - buf = socketReadAll(sock, &len); - - printf("GOT '%s'\n", buf); - -bail: - sock.close(); - free(buf); -} - diff --git a/libs/utils/Static.cpp b/libs/utils/Static.cpp deleted file mode 100644 index 93f7e4f..0000000 --- a/libs/utils/Static.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// All static variables go here, to control initialization and -// destruction order in the library. - -#include <private/utils/Static.h> - -#include <utils/BufferedTextOutput.h> -#include <utils/IPCThreadState.h> -#include <utils/Log.h> - -namespace android { - -class LibUtilsFirstStatics -{ -public: - LibUtilsFirstStatics() - { - initialize_string8(); - initialize_string16(); - } - - ~LibUtilsFirstStatics() - { - terminate_string16(); - terminate_string8(); - } -}; - -static LibUtilsFirstStatics gFirstStatics; -int gDarwinCantLoadAllObjects = 1; - -// ------------ Text output streams - -Vector<int32_t> gTextBuffers; - -class LogTextOutput : public BufferedTextOutput -{ -public: - LogTextOutput() : BufferedTextOutput(MULTITHREADED) { } - virtual ~LogTextOutput() { }; - -protected: - virtual status_t writeLines(const struct iovec& vec, size_t N) - { - android_writevLog(&vec, N); - return NO_ERROR; - } -}; - -class FdTextOutput : public BufferedTextOutput -{ -public: - FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { } - virtual ~FdTextOutput() { }; - -protected: - virtual status_t writeLines(const struct iovec& vec, size_t N) - { - writev(mFD, &vec, N); - return NO_ERROR; - } - -private: - int mFD; -}; - -static LogTextOutput gLogTextOutput; -static FdTextOutput gStdoutTextOutput(STDOUT_FILENO); -static FdTextOutput gStderrTextOutput(STDERR_FILENO); - -TextOutput& alog(gLogTextOutput); -TextOutput& aout(gStdoutTextOutput); -TextOutput& aerr(gStderrTextOutput); - -#ifndef LIBUTILS_NATIVE - -// ------------ ProcessState.cpp - -Mutex gProcessMutex; -sp<ProcessState> gProcess; - -class LibUtilsIPCtStatics -{ -public: - LibUtilsIPCtStatics() - { - } - - ~LibUtilsIPCtStatics() - { - IPCThreadState::shutdown(); - } -}; - -static LibUtilsIPCtStatics gIPCStatics; - -// ------------ ServiceManager.cpp - -Mutex gDefaultServiceManagerLock; -sp<IServiceManager> gDefaultServiceManager; -sp<IPermissionController> gPermissionController; - -#endif - -} // namespace android diff --git a/libs/utils/StopWatch.cpp b/libs/utils/StopWatch.cpp deleted file mode 100644 index 68a1c52..0000000 --- a/libs/utils/StopWatch.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "StopWatch" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include <utils/Log.h> -#include <utils/Errors.h> -#include <utils/StopWatch.h> - -/*****************************************************************************/ - -namespace android { - - -StopWatch::StopWatch(const char *name, int clock, uint32_t flags) - : mName(name), mClock(clock), mFlags(flags), - mStartTime(0), mNumLaps(0) -{ - mStartTime = systemTime(mClock); -} - -StopWatch::~StopWatch() -{ - nsecs_t elapsed = elapsedTime(); - const int n = mNumLaps; - LOGD("StopWatch %s (us): %lld ", mName, ns2us(elapsed)); - for (int i=0 ; i<n ; i++) { - const nsecs_t soFar = mLaps[i].soFar; - const nsecs_t thisLap = mLaps[i].thisLap; - LOGD(" [%d: %lld, %lld]", i, ns2us(soFar), ns2us(thisLap)); - } -} - -const char* StopWatch::name() const -{ - return mName; -} - -nsecs_t StopWatch::lap() -{ - nsecs_t elapsed = elapsedTime(); - if (mNumLaps >= 8) { - elapsed = 0; - } else { - const int n = mNumLaps; - mLaps[n].soFar = elapsed; - mLaps[n].thisLap = n ? (elapsed - mLaps[n-1].soFar) : elapsed; - mNumLaps = n+1; - } - return elapsed; -} - -nsecs_t StopWatch::elapsedTime() const -{ - return systemTime(mClock) - mStartTime; -} - - -/*****************************************************************************/ - -}; // namespace android - diff --git a/libs/utils/String16.cpp b/libs/utils/String16.cpp deleted file mode 100644 index 1f81cad..0000000 --- a/libs/utils/String16.cpp +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/String16.h> - -#include <utils/Debug.h> -#include <utils/Log.h> -#include <utils/String8.h> -#include <utils/TextOutput.h> -#include <utils/threads.h> - -#include <private/utils/Static.h> - -#ifdef HAVE_WINSOCK -# undef nhtol -# undef htonl -# undef nhtos -# undef htons - -# ifdef HAVE_LITTLE_ENDIAN -# define ntohl(x) ( ((x) << 24) | (((x) >> 24) & 255) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) ) -# define htonl(x) ntohl(x) -# define ntohs(x) ( (((x) << 8) & 0xff00) | (((x) >> 8) & 255) ) -# define htons(x) ntohs(x) -# else -# define ntohl(x) (x) -# define htonl(x) (x) -# define ntohs(x) (x) -# define htons(x) (x) -# endif -#else -# include <netinet/in.h> -#endif - -#include <memory.h> -#include <stdio.h> -#include <ctype.h> - -// --------------------------------------------------------------------------- - -int strcmp16(const char16_t *s1, const char16_t *s2) -{ - char16_t ch; - int d = 0; - - while ( 1 ) { - d = (int)(ch = *s1++) - (int)*s2++; - if ( d || !ch ) - break; - } - - return d; -} - -int strncmp16(const char16_t *s1, const char16_t *s2, size_t n) -{ - char16_t ch; - int d = 0; - - while ( n-- ) { - d = (int)(ch = *s1++) - (int)*s2++; - if ( d || !ch ) - break; - } - - return d; -} - -char16_t *strcpy16(char16_t *dst, const char16_t *src) -{ - char16_t *q = dst; - const char16_t *p = src; - char16_t ch; - - do { - *q++ = ch = *p++; - } while ( ch ); - - return dst; -} - -size_t strlen16(const char16_t *s) -{ - const char16_t *ss = s; - while ( *ss ) - ss++; - return ss-s; -} - - -char16_t *strncpy16(char16_t *dst, const char16_t *src, size_t n) -{ - char16_t *q = dst; - const char16_t *p = src; - char ch; - - while (n) { - n--; - *q++ = ch = *p++; - if ( !ch ) - break; - } - - *q = 0; - - return dst; -} - -size_t strnlen16(const char16_t *s, size_t maxlen) -{ - const char16_t *ss = s; - - /* Important: the maxlen test must precede the reference through ss; - since the byte beyond the maximum may segfault */ - while ((maxlen > 0) && *ss) { - ss++; - maxlen--; - } - return ss-s; -} - -int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2) -{ - const char16_t* e1 = s1+n1; - const char16_t* e2 = s2+n2; - - while (s1 < e1 && s2 < e2) { - const int d = (int)*s1++ - (int)*s2++; - if (d) { - return d; - } - } - - return n1 < n2 - ? (0 - (int)*s2) - : (n1 > n2 - ? ((int)*s1 - 0) - : 0); -} - -int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2) -{ - const char16_t* e1 = s1H+n1; - const char16_t* e2 = s2N+n2; - - while (s1H < e1 && s2N < e2) { - const char16_t c2 = ntohs(*s2N); - const int d = (int)*s1H++ - (int)c2; - s2N++; - if (d) { - return d; - } - } - - return n1 < n2 - ? (0 - (int)ntohs(*s2N)) - : (n1 > n2 - ? ((int)*s1H - 0) - : 0); -} - -// --------------------------------------------------------------------------- - -namespace android { - -static inline size_t -utf8_char_len(uint8_t ch) -{ - return ((0xe5000000 >> ((ch >> 3) & 0x1e)) & 3) + 1; -} - -#define UTF8_SHIFT_AND_MASK(unicode, byte) (unicode)<<=6; (unicode) |= (0x3f & (byte)); - -static inline uint32_t -utf8_to_utf32(const uint8_t *src, size_t length) -{ - uint32_t unicode; - - switch (length) - { - case 1: - return src[0]; - case 2: - unicode = src[0] & 0x1f; - UTF8_SHIFT_AND_MASK(unicode, src[1]) - return unicode; - case 3: - unicode = src[0] & 0x0f; - UTF8_SHIFT_AND_MASK(unicode, src[1]) - UTF8_SHIFT_AND_MASK(unicode, src[2]) - return unicode; - case 4: - unicode = src[0] & 0x07; - UTF8_SHIFT_AND_MASK(unicode, src[1]) - UTF8_SHIFT_AND_MASK(unicode, src[2]) - UTF8_SHIFT_AND_MASK(unicode, src[3]) - return unicode; - default: - return 0xffff; - } - - //printf("Char at %p: len=%d, utf-16=%p\n", src, length, (void*)result); -} - -// --------------------------------------------------------------------------- - -static SharedBuffer* gEmptyStringBuf = NULL; -static char16_t* gEmptyString = NULL; - -static inline char16_t* getEmptyString() -{ - gEmptyStringBuf->acquire(); - return gEmptyString; -} - -void initialize_string16() -{ - SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)); - char16_t* str = (char16_t*)buf->data(); - *str = 0; - gEmptyStringBuf = buf; - gEmptyString = str; -} - -void terminate_string16() -{ - SharedBuffer::bufferFromData(gEmptyString)->release(); - gEmptyStringBuf = NULL; - gEmptyString = NULL; -} - -// --------------------------------------------------------------------------- - -// Note: not dealing with generating surrogate pairs. -static char16_t* allocFromUTF8(const char* in, size_t len) -{ - if (len == 0) return getEmptyString(); - - size_t chars = 0; - const char* end = in+len; - const char* p = in; - - while (p < end) { - chars++; - p += utf8_char_len(*p); - } - - SharedBuffer* buf = SharedBuffer::alloc((chars+1)*sizeof(char16_t)); - if (buf) { - p = in; - char16_t* str = (char16_t*)buf->data(); - char16_t* d = str; - while (p < end) { - size_t len = utf8_char_len(*p); - *d++ = (char16_t)utf8_to_utf32((const uint8_t*)p, len); - p += len; - } - *d = 0; - - //printf("Created UTF-16 string from UTF-8 \"%s\":", in); - //printHexData(1, str, buf->size(), 16, 1); - //printf("\n"); - - return str; - } - - return getEmptyString(); -} - -// --------------------------------------------------------------------------- - -String16::String16() - : mString(getEmptyString()) -{ -} - -String16::String16(const String16& o) - : mString(o.mString) -{ - SharedBuffer::bufferFromData(mString)->acquire(); -} - -String16::String16(const String16& o, size_t len, size_t begin) - : mString(getEmptyString()) -{ - setTo(o, len, begin); -} - -String16::String16(const char16_t* o) -{ - size_t len = strlen16(o); - SharedBuffer* buf = SharedBuffer::alloc((len+1)*sizeof(char16_t)); - LOG_ASSERT(buf, "Unable to allocate shared buffer"); - if (buf) { - char16_t* str = (char16_t*)buf->data(); - strcpy16(str, o); - mString = str; - return; - } - - mString = getEmptyString(); -} - -String16::String16(const char16_t* o, size_t len) -{ - SharedBuffer* buf = SharedBuffer::alloc((len+1)*sizeof(char16_t)); - LOG_ASSERT(buf, "Unable to allocate shared buffer"); - if (buf) { - char16_t* str = (char16_t*)buf->data(); - memcpy(str, o, len*sizeof(char16_t)); - str[len] = 0; - mString = str; - return; - } - - mString = getEmptyString(); -} - -String16::String16(const String8& o) - : mString(allocFromUTF8(o.string(), o.size())) -{ -} - -String16::String16(const char* o) - : mString(allocFromUTF8(o, strlen(o))) -{ -} - -String16::String16(const char* o, size_t len) - : mString(allocFromUTF8(o, len)) -{ -} - -String16::~String16() -{ - SharedBuffer::bufferFromData(mString)->release(); -} - -void String16::setTo(const String16& other) -{ - SharedBuffer::bufferFromData(other.mString)->acquire(); - SharedBuffer::bufferFromData(mString)->release(); - mString = other.mString; -} - -status_t String16::setTo(const String16& other, size_t len, size_t begin) -{ - const size_t N = other.size(); - if (begin >= N) { - SharedBuffer::bufferFromData(mString)->release(); - mString = getEmptyString(); - return NO_ERROR; - } - if ((begin+len) > N) len = N-begin; - if (begin == 0 && len == N) { - setTo(other); - return NO_ERROR; - } - - if (&other == this) { - LOG_ALWAYS_FATAL("Not implemented"); - } - - return setTo(other.string()+begin, len); -} - -status_t String16::setTo(const char16_t* other) -{ - return setTo(other, strlen16(other)); -} - -status_t String16::setTo(const char16_t* other, size_t len) -{ - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize((len+1)*sizeof(char16_t)); - if (buf) { - char16_t* str = (char16_t*)buf->data(); - memcpy(str, other, len*sizeof(char16_t)); - str[len] = 0; - mString = str; - return NO_ERROR; - } - return NO_MEMORY; -} - -status_t String16::append(const String16& other) -{ - const size_t myLen = size(); - const size_t otherLen = other.size(); - if (myLen == 0) { - setTo(other); - return NO_ERROR; - } else if (otherLen == 0) { - return NO_ERROR; - } - - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize((myLen+otherLen+1)*sizeof(char16_t)); - if (buf) { - char16_t* str = (char16_t*)buf->data(); - memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t)); - mString = str; - return NO_ERROR; - } - return NO_MEMORY; -} - -status_t String16::append(const char16_t* chrs, size_t otherLen) -{ - const size_t myLen = size(); - if (myLen == 0) { - setTo(chrs, otherLen); - return NO_ERROR; - } else if (otherLen == 0) { - return NO_ERROR; - } - - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize((myLen+otherLen+1)*sizeof(char16_t)); - if (buf) { - char16_t* str = (char16_t*)buf->data(); - memcpy(str+myLen, chrs, otherLen*sizeof(char16_t)); - str[myLen+otherLen] = 0; - mString = str; - return NO_ERROR; - } - return NO_MEMORY; -} - -status_t String16::insert(size_t pos, const char16_t* chrs) -{ - return insert(pos, chrs, strlen16(chrs)); -} - -status_t String16::insert(size_t pos, const char16_t* chrs, size_t len) -{ - const size_t myLen = size(); - if (myLen == 0) { - return setTo(chrs, len); - return NO_ERROR; - } else if (len == 0) { - return NO_ERROR; - } - - if (pos > myLen) pos = myLen; - - #if 0 - printf("Insert in to %s: pos=%d, len=%d, myLen=%d, chrs=%s\n", - String8(*this).string(), pos, - len, myLen, String8(chrs, len).string()); - #endif - - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize((myLen+len+1)*sizeof(char16_t)); - if (buf) { - char16_t* str = (char16_t*)buf->data(); - if (pos < myLen) { - memmove(str+pos+len, str+pos, (myLen-pos)*sizeof(char16_t)); - } - memcpy(str+pos, chrs, len*sizeof(char16_t)); - str[myLen+len] = 0; - mString = str; - #if 0 - printf("Result (%d chrs): %s\n", size(), String8(*this).string()); - #endif - return NO_ERROR; - } - return NO_MEMORY; -} - -ssize_t String16::findFirst(char16_t c) const -{ - const char16_t* str = string(); - const char16_t* p = str; - const char16_t* e = p + size(); - while (p < e) { - if (*p == c) { - return p-str; - } - p++; - } - return -1; -} - -ssize_t String16::findLast(char16_t c) const -{ - const char16_t* str = string(); - const char16_t* p = str; - const char16_t* e = p + size(); - while (p < e) { - e--; - if (*e == c) { - return e-str; - } - } - return -1; -} - -bool String16::startsWith(const String16& prefix) const -{ - const size_t ps = prefix.size(); - if (ps > size()) return false; - return strzcmp16(mString, ps, prefix.string(), ps) == 0; -} - -bool String16::startsWith(const char16_t* prefix) const -{ - const size_t ps = strlen16(prefix); - if (ps > size()) return false; - return strncmp16(mString, prefix, ps) == 0; -} - -status_t String16::makeLower() -{ - const size_t N = size(); - const char16_t* str = string(); - char16_t* edit = NULL; - for (size_t i=0; i<N; i++) { - const char16_t v = str[i]; - if (v >= 'A' && v <= 'Z') { - if (!edit) { - SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit(); - if (!buf) { - return NO_MEMORY; - } - edit = (char16_t*)buf->data(); - mString = str = edit; - } - edit[i] = tolower((char)v); - } - } - return NO_ERROR; -} - -status_t String16::replaceAll(char16_t replaceThis, char16_t withThis) -{ - const size_t N = size(); - const char16_t* str = string(); - char16_t* edit = NULL; - for (size_t i=0; i<N; i++) { - if (str[i] == replaceThis) { - if (!edit) { - SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit(); - if (!buf) { - return NO_MEMORY; - } - edit = (char16_t*)buf->data(); - mString = str = edit; - } - edit[i] = withThis; - } - } - return NO_ERROR; -} - -status_t String16::remove(size_t len, size_t begin) -{ - const size_t N = size(); - if (begin >= N) { - SharedBuffer::bufferFromData(mString)->release(); - mString = getEmptyString(); - return NO_ERROR; - } - if ((begin+len) > N) len = N-begin; - if (begin == 0 && len == N) { - return NO_ERROR; - } - - if (begin > 0) { - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize((N+1)*sizeof(char16_t)); - if (!buf) { - return NO_MEMORY; - } - char16_t* str = (char16_t*)buf->data(); - memmove(str, str+begin, (N-begin+1)*sizeof(char16_t)); - mString = str; - } - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize((len+1)*sizeof(char16_t)); - if (buf) { - char16_t* str = (char16_t*)buf->data(); - str[len] = 0; - mString = str; - return NO_ERROR; - } - return NO_MEMORY; -} - -TextOutput& operator<<(TextOutput& to, const String16& val) -{ - to << String8(val).string(); - return to; -} - -}; // namespace android diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp deleted file mode 100644 index c50d343..0000000 --- a/libs/utils/String8.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/String8.h> - -#include <utils/Log.h> -#include <utils/String16.h> -#include <utils/TextOutput.h> -#include <utils/threads.h> - -#include <private/utils/Static.h> - -#include <ctype.h> - -namespace android { - -// --------------------------------------------------------------------------- - -static const uint32_t kByteMask = 0x000000BF; -static const uint32_t kByteMark = 0x00000080; - -// Surrogates aren't valid for UTF-32 characters, so define some -// constants that will let us screen them out. -static const uint32_t kUnicodeSurrogateHighStart = 0x0000D800; -static const uint32_t kUnicodeSurrogateHighEnd = 0x0000DBFF; -static const uint32_t kUnicodeSurrogateLowStart = 0x0000DC00; -static const uint32_t kUnicodeSurrogateLowEnd = 0x0000DFFF; -static const uint32_t kUnicodeSurrogateStart = kUnicodeSurrogateHighStart; -static const uint32_t kUnicodeSurrogateEnd = kUnicodeSurrogateLowEnd; - -// Mask used to set appropriate bits in first byte of UTF-8 sequence, -// indexed by number of bytes in the sequence. -static const uint32_t kFirstByteMark[] = { - 0x00000000, 0x00000000, 0x000000C0, 0x000000E0, 0x000000F0 -}; - -// Separator used by resource paths. This is not platform dependent contrary -// to OS_PATH_SEPARATOR. -#define RES_PATH_SEPARATOR '/' - -// Return number of utf8 bytes required for the character. -static size_t utf32_to_utf8_bytes(uint32_t srcChar) -{ - size_t bytesToWrite; - - // Figure out how many bytes the result will require. - if (srcChar < 0x00000080) - { - bytesToWrite = 1; - } - else if (srcChar < 0x00000800) - { - bytesToWrite = 2; - } - else if (srcChar < 0x00010000) - { - if ((srcChar < kUnicodeSurrogateStart) - || (srcChar > kUnicodeSurrogateEnd)) - { - bytesToWrite = 3; - } - else - { - // Surrogates are invalid UTF-32 characters. - return 0; - } - } - // Max code point for Unicode is 0x0010FFFF. - else if (srcChar < 0x00110000) - { - bytesToWrite = 4; - } - else - { - // Invalid UTF-32 character. - return 0; - } - - return bytesToWrite; -} - -// Write out the source character to <dstP>. - -static void utf32_to_utf8(uint8_t* dstP, uint32_t srcChar, size_t bytes) -{ - dstP += bytes; - switch (bytes) - { /* note: everything falls through. */ - case 4: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6; - case 3: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6; - case 2: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6; - case 1: *--dstP = (uint8_t)(srcChar | kFirstByteMark[bytes]); - } -} - -// --------------------------------------------------------------------------- - -static SharedBuffer* gEmptyStringBuf = NULL; -static char* gEmptyString = NULL; - -extern int gDarwinCantLoadAllObjects; -int gDarwinIsReallyAnnoying; - -static inline char* getEmptyString() -{ - gEmptyStringBuf->acquire(); - return gEmptyString; -} - -void initialize_string8() -{ -#ifdef LIBUTILS_NATIVE - // Bite me, Darwin! - gDarwinIsReallyAnnoying = gDarwinCantLoadAllObjects; -#endif - - SharedBuffer* buf = SharedBuffer::alloc(1); - char* str = (char*)buf->data(); - *str = 0; - gEmptyStringBuf = buf; - gEmptyString = str; -} - -void terminate_string8() -{ - SharedBuffer::bufferFromData(gEmptyString)->release(); - gEmptyStringBuf = NULL; - gEmptyString = NULL; -} - -// --------------------------------------------------------------------------- - -static char* allocFromUTF8(const char* in, size_t len) -{ - if (len > 0) { - SharedBuffer* buf = SharedBuffer::alloc(len+1); - LOG_ASSERT(buf, "Unable to allocate shared buffer"); - if (buf) { - char* str = (char*)buf->data(); - memcpy(str, in, len); - str[len] = 0; - return str; - } - return NULL; - } - - return getEmptyString(); -} - -// Note: not dealing with expanding surrogate pairs. -static char* allocFromUTF16(const char16_t* in, size_t len) -{ - if (len == 0) return getEmptyString(); - - size_t bytes = 0; - const char16_t* end = in+len; - const char16_t* p = in; - - while (p < end) { - bytes += utf32_to_utf8_bytes(*p); - p++; - } - - SharedBuffer* buf = SharedBuffer::alloc(bytes+1); - LOG_ASSERT(buf, "Unable to allocate shared buffer"); - if (buf) { - p = in; - char* str = (char*)buf->data(); - char* d = str; - while (p < end) { - uint32_t c = *p++; - size_t len = utf32_to_utf8_bytes(c); - utf32_to_utf8((uint8_t*)d, c, len); - d += len; - } - *d = 0; - - return str; - } - - return getEmptyString(); -} - -// --------------------------------------------------------------------------- - -String8::String8() - : mString(getEmptyString()) -{ -} - -String8::String8(const String8& o) - : mString(o.mString) -{ - SharedBuffer::bufferFromData(mString)->acquire(); -} - -String8::String8(const char* o) - : mString(allocFromUTF8(o, strlen(o))) -{ - if (mString == NULL) { - mString = getEmptyString(); - } -} - -String8::String8(const char* o, size_t len) - : mString(allocFromUTF8(o, len)) -{ - if (mString == NULL) { - mString = getEmptyString(); - } -} - -String8::String8(const String16& o) - : mString(allocFromUTF16(o.string(), o.size())) -{ -} - -String8::String8(const char16_t* o) - : mString(allocFromUTF16(o, strlen16(o))) -{ -} - -String8::String8(const char16_t* o, size_t len) - : mString(allocFromUTF16(o, len)) -{ -} - -String8::~String8() -{ - SharedBuffer::bufferFromData(mString)->release(); -} - -void String8::setTo(const String8& other) -{ - SharedBuffer::bufferFromData(other.mString)->acquire(); - SharedBuffer::bufferFromData(mString)->release(); - mString = other.mString; -} - -status_t String8::setTo(const char* other) -{ - SharedBuffer::bufferFromData(mString)->release(); - mString = allocFromUTF8(other, strlen(other)); - if (mString) return NO_ERROR; - - mString = getEmptyString(); - return NO_MEMORY; -} - -status_t String8::setTo(const char* other, size_t len) -{ - SharedBuffer::bufferFromData(mString)->release(); - mString = allocFromUTF8(other, len); - if (mString) return NO_ERROR; - - mString = getEmptyString(); - return NO_MEMORY; -} - -status_t String8::setTo(const char16_t* other, size_t len) -{ - SharedBuffer::bufferFromData(mString)->release(); - mString = allocFromUTF16(other, len); - if (mString) return NO_ERROR; - - mString = getEmptyString(); - return NO_MEMORY; -} - -status_t String8::append(const String8& other) -{ - const size_t otherLen = other.bytes(); - if (bytes() == 0) { - setTo(other); - return NO_ERROR; - } else if (otherLen == 0) { - return NO_ERROR; - } - - return real_append(other.string(), otherLen); -} - -status_t String8::append(const char* other) -{ - return append(other, strlen(other)); -} - -status_t String8::append(const char* other, size_t otherLen) -{ - if (bytes() == 0) { - return setTo(other, otherLen); - } else if (otherLen == 0) { - return NO_ERROR; - } - - return real_append(other, otherLen); -} - -status_t String8::real_append(const char* other, size_t otherLen) -{ - const size_t myLen = bytes(); - - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize(myLen+otherLen+1); - if (buf) { - char* str = (char*)buf->data(); - mString = str; - str += myLen; - memcpy(str, other, otherLen); - str[otherLen] = '\0'; - return NO_ERROR; - } - return NO_MEMORY; -} - -char* String8::lockBuffer(size_t size) -{ - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize(size+1); - if (buf) { - char* str = (char*)buf->data(); - mString = str; - return str; - } - return NULL; -} - -void String8::unlockBuffer() -{ - unlockBuffer(strlen(mString)); -} - -status_t String8::unlockBuffer(size_t size) -{ - if (size != this->size()) { - SharedBuffer* buf = SharedBuffer::bufferFromData(mString) - ->editResize(size+1); - if (buf) { - char* str = (char*)buf->data(); - str[size] = 0; - mString = str; - return NO_ERROR; - } - } - - return NO_MEMORY; -} - -ssize_t String8::find(const char* other, size_t start) const -{ - size_t len = size(); - if (start >= len) { - return -1; - } - const char* s = mString+start; - const char* p = strstr(s, other); - return p ? p-mString : -1; -} - -void String8::toLower() -{ - toLower(0, size()); -} - -void String8::toLower(size_t start, size_t length) -{ - const size_t len = size(); - if (start >= len) { - return; - } - if (start+length > len) { - length = len-start; - } - char* buf = lockBuffer(len); - buf += start; - while (length > 0) { - *buf = tolower(*buf); - buf++; - length--; - } - unlockBuffer(len); -} - -void String8::toUpper() -{ - toUpper(0, size()); -} - -void String8::toUpper(size_t start, size_t length) -{ - const size_t len = size(); - if (start >= len) { - return; - } - if (start+length > len) { - length = len-start; - } - char* buf = lockBuffer(len); - buf += start; - while (length > 0) { - *buf = toupper(*buf); - buf++; - length--; - } - unlockBuffer(len); -} - -TextOutput& operator<<(TextOutput& to, const String8& val) -{ - to << val.string(); - return to; -} - -// --------------------------------------------------------------------------- -// Path functions - - -void String8::setPathName(const char* name) -{ - setPathName(name, strlen(name)); -} - -void String8::setPathName(const char* name, size_t len) -{ - char* buf = lockBuffer(len); - - memcpy(buf, name, len); - - // remove trailing path separator, if present - if (len > 0 && buf[len-1] == OS_PATH_SEPARATOR) - len--; - - buf[len] = '\0'; - - unlockBuffer(len); -} - -String8 String8::getPathLeaf(void) const -{ - const char* cp; - const char*const buf = mString; - - cp = strrchr(buf, OS_PATH_SEPARATOR); - if (cp == NULL) - return String8(*this); - else - return String8(cp+1); -} - -String8 String8::getPathDir(void) const -{ - const char* cp; - const char*const str = mString; - - cp = strrchr(str, OS_PATH_SEPARATOR); - if (cp == NULL) - return String8(""); - else - return String8(str, cp - str); -} - -String8 String8::walkPath(String8* outRemains) const -{ - const char* cp; - const char*const str = mString; - const char* buf = str; - - cp = strchr(buf, OS_PATH_SEPARATOR); - if (cp == buf) { - // don't include a leading '/'. - buf = buf+1; - cp = strchr(buf, OS_PATH_SEPARATOR); - } - - if (cp == NULL) { - String8 res = buf != str ? String8(buf) : *this; - if (outRemains) *outRemains = String8(""); - return res; - } - - String8 res(buf, cp-buf); - if (outRemains) *outRemains = String8(cp+1); - return res; -} - -/* - * Helper function for finding the start of an extension in a pathname. - * - * Returns a pointer inside mString, or NULL if no extension was found. - */ -char* String8::find_extension(void) const -{ - const char* lastSlash; - const char* lastDot; - int extLen; - const char* const str = mString; - - // only look at the filename - lastSlash = strrchr(str, OS_PATH_SEPARATOR); - if (lastSlash == NULL) - lastSlash = str; - else - lastSlash++; - - // find the last dot - lastDot = strrchr(lastSlash, '.'); - if (lastDot == NULL) - return NULL; - - // looks good, ship it - return const_cast<char*>(lastDot); -} - -String8 String8::getPathExtension(void) const -{ - char* ext; - - ext = find_extension(); - if (ext != NULL) - return String8(ext); - else - return String8(""); -} - -String8 String8::getBasePath(void) const -{ - char* ext; - const char* const str = mString; - - ext = find_extension(); - if (ext == NULL) - return String8(*this); - else - return String8(str, ext - str); -} - -String8& String8::appendPath(const char* name) -{ - // TODO: The test below will fail for Win32 paths. Fix later or ignore. - if (name[0] != OS_PATH_SEPARATOR) { - if (*name == '\0') { - // nothing to do - return *this; - } - - size_t len = length(); - if (len == 0) { - // no existing filename, just use the new one - setPathName(name); - return *this; - } - - // make room for oldPath + '/' + newPath - int newlen = strlen(name); - - char* buf = lockBuffer(len+1+newlen); - - // insert a '/' if needed - if (buf[len-1] != OS_PATH_SEPARATOR) - buf[len++] = OS_PATH_SEPARATOR; - - memcpy(buf+len, name, newlen+1); - len += newlen; - - unlockBuffer(len); - - return *this; - } else { - setPathName(name); - return *this; - } -} - -String8& String8::convertToResPath() -{ -#if OS_PATH_SEPARATOR != RES_PATH_SEPARATOR - size_t len = length(); - if (len > 0) { - char * buf = lockBuffer(len); - for (char * end = buf + len; buf < end; ++buf) { - if (*buf == OS_PATH_SEPARATOR) - *buf = RES_PATH_SEPARATOR; - } - unlockBuffer(len); - } -#endif - return *this; -} - - -}; // namespace android diff --git a/libs/utils/SystemClock.cpp b/libs/utils/SystemClock.cpp deleted file mode 100644 index 2bdc0ce..0000000 --- a/libs/utils/SystemClock.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -/* - * System clock functions. - */ - -#if HAVE_ANDROID_OS -#include <linux/ioctl.h> -#include <linux/rtc.h> -#include <utils/Atomic.h> -#include <linux/android_alarm.h> -#endif - -#include <sys/time.h> -#include <limits.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> - -#include <utils/SystemClock.h> -#include <utils/Timers.h> - -#define LOG_TAG "SystemClock" -#include "utils/Log.h" - -namespace android { - -/* - * Set the current time. This only works when running as root. - */ -int setCurrentTimeMillis(int64_t millis) -{ -#if WIN32 - // not implemented - return -1; -#else - struct timeval tv; -#if HAVE_ANDROID_OS - struct timespec ts; - int fd; - int res; -#endif - int ret = 0; - - if (millis <= 0 || millis / 1000LL >= INT_MAX) { - return -1; - } - - tv.tv_sec = (time_t) (millis / 1000LL); - tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); - - LOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); - -#if HAVE_ANDROID_OS - fd = open("/dev/alarm", O_RDWR); - if(fd < 0) { - LOGW("Unable to open alarm driver: %s\n", strerror(errno)); - return -1; - } - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000; - res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); - if(res < 0) { - LOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); - ret = -1; - } - close(fd); -#else - if (settimeofday(&tv, NULL) != 0) { - LOGW("Unable to set clock to %d.%d: %s\n", - (int) tv.tv_sec, (int) tv.tv_usec, strerror(errno)); - ret = -1; - } -#endif - - return ret; -#endif // WIN32 -} - -/* - * native public static long uptimeMillis(); - */ -int64_t uptimeMillis() -{ - int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); - return (int64_t) nanoseconds_to_milliseconds(when); -} - -/* - * native public static long elapsedRealtime(); - */ -int64_t elapsedRealtime() -{ -#if HAVE_ANDROID_OS - static int s_fd = -1; - - if (s_fd == -1) { - int fd = open("/dev/alarm", O_RDONLY); - if (android_atomic_cmpxchg(-1, fd, &s_fd)) { - close(fd); - } - } - - struct timespec ts; - int result = ioctl(s_fd, - ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts); - - if (result == 0) { - int64_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; - return (int64_t) nanoseconds_to_milliseconds(when); - } else { - // XXX: there was an error, probably because the driver didn't - // exist ... this should return - // a real error, like an exception! - int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); - return (int64_t) nanoseconds_to_milliseconds(when); - } -#else - int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); - return (int64_t) nanoseconds_to_milliseconds(when); -#endif -} - -}; // namespace android diff --git a/libs/utils/TextOutput.cpp b/libs/utils/TextOutput.cpp deleted file mode 100644 index cebee99..0000000 --- a/libs/utils/TextOutput.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/TextOutput.h> - -#include <utils/Debug.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -// --------------------------------------------------------------------------- - -namespace android { - -TextOutput& operator<<(TextOutput& to, bool val) -{ - if (val) to.print("true", 4); - else to.print("false", 5); - return to; -} - -TextOutput& operator<<(TextOutput& to, int val) -{ - char buf[16]; - sprintf(buf, "%d", val); - to.print(buf, strlen(buf)); - return to; -} - -TextOutput& operator<<(TextOutput& to, long val) -{ - char buf[16]; - sprintf(buf, "%ld", val); - to.print(buf, strlen(buf)); - return to; -} - -TextOutput& operator<<(TextOutput& to, unsigned int val) -{ - char buf[16]; - sprintf(buf, "%u", val); - to.print(buf, strlen(buf)); - return to; -} - -TextOutput& operator<<(TextOutput& to, unsigned long val) -{ - char buf[16]; - sprintf(buf, "%lu", val); - to.print(buf, strlen(buf)); - return to; -} - -TextOutput& operator<<(TextOutput& to, long long val) -{ - char buf[32]; - sprintf(buf, "%Ld", val); - to.print(buf, strlen(buf)); - return to; -} - -TextOutput& operator<<(TextOutput& to, unsigned long long val) -{ - char buf[32]; - sprintf(buf, "%Lu", val); - to.print(buf, strlen(buf)); - return to; -} - -static TextOutput& print_float(TextOutput& to, double value) -{ - char buf[64]; - sprintf(buf, "%g", value); - if( !strchr(buf, '.') && !strchr(buf, 'e') && - !strchr(buf, 'E') ) { - strncat(buf, ".0", sizeof(buf)-1); - } - to.print(buf, strlen(buf)); - return to; -} - -TextOutput& operator<<(TextOutput& to, float val) -{ - return print_float(to,val); -} - -TextOutput& operator<<(TextOutput& to, double val) -{ - return print_float(to,val); -} - -TextOutput& operator<<(TextOutput& to, const void* val) -{ - char buf[16]; - sprintf(buf, "%p", val); - to.print(buf, strlen(buf)); - return to; -} - -static void textOutputPrinter(void* cookie, const char* txt) -{ - ((TextOutput*)cookie)->print(txt, strlen(txt)); -} - -TextOutput& operator<<(TextOutput& to, const TypeCode& val) -{ - printTypeCode(val.typeCode(), textOutputPrinter, (void*)&to); - return to; -} - -HexDump::HexDump(const void *buf, size_t size, size_t bytesPerLine) - : mBuffer(buf) - , mSize(size) - , mBytesPerLine(bytesPerLine) - , mSingleLineCutoff(16) - , mAlignment(4) - , mCArrayStyle(false) -{ - if (bytesPerLine >= 16) mAlignment = 4; - else if (bytesPerLine >= 8) mAlignment = 2; - else mAlignment = 1; -} - -TextOutput& operator<<(TextOutput& to, const HexDump& val) -{ - printHexData(0, val.buffer(), val.size(), val.bytesPerLine(), - val.singleLineCutoff(), val.alignment(), val.carrayStyle(), - textOutputPrinter, (void*)&to); - return to; -} - -}; // namespace android diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp deleted file mode 100644 index 74271ba..0000000 --- a/libs/utils/Threads.cpp +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "libutils.threads" - -#include <utils/threads.h> -#include <utils/Log.h> - -#include <stdio.h> -#include <stdlib.h> -#include <memory.h> -#include <errno.h> -#include <assert.h> -#include <unistd.h> - -#if defined(HAVE_PTHREADS) -# include <pthread.h> -# include <sched.h> -# include <sys/resource.h> -#elif defined(HAVE_WIN32_THREADS) -# include <windows.h> -# include <stdint.h> -# include <process.h> -# define HAVE_CREATETHREAD // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW -#endif - -#if defined(HAVE_FUTEX) -#include <private/utils/futex_synchro.h> -#endif - -#if defined(HAVE_PRCTL) -#include <sys/prctl.h> -#endif - -/* - * =========================================================================== - * Thread wrappers - * =========================================================================== - */ - -using namespace android; - -// ---------------------------------------------------------------------------- -#if defined(HAVE_PTHREADS) -#if 0 -#pragma mark - -#pragma mark PTHREAD -#endif -// ---------------------------------------------------------------------------- - -/* - * Create and run a new thead. - * - * We create it "detached", so it cleans up after itself. - */ - -typedef void* (*android_pthread_entry)(void*); - -struct thread_data_t { - thread_func_t entryFunction; - void* userData; - int priority; - char * threadName; - - // we use this trampoline when we need to set the priority with - // nice/setpriority. - static int trampoline(const thread_data_t* t) { - thread_func_t f = t->entryFunction; - void* u = t->userData; - int prio = t->priority; - char * name = t->threadName; - delete t; - setpriority(PRIO_PROCESS, 0, prio); - if (name) { -#if defined(HAVE_PRCTL) - // Mac OS doesn't have this, and we build libutil for the host too - int hasAt = 0; - int hasDot = 0; - char *s = name; - while (*s) { - if (*s == '.') hasDot = 1; - else if (*s == '@') hasAt = 1; - s++; - } - int len = s - name; - if (len < 15 || hasAt || !hasDot) { - s = name; - } else { - s = name + len - 15; - } - prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0); -#endif - free(name); - } - return f(u); - } -}; - -int androidCreateRawThreadEtc(android_thread_func_t entryFunction, - void *userData, - const char* threadName, - int32_t threadPriority, - size_t threadStackSize, - android_thread_id_t *threadId) -{ - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - -#ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */ - if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) { - // We could avoid the trampoline if there was a way to get to the - // android_thread_id_t (pid) from pthread_t - thread_data_t* t = new thread_data_t; - t->priority = threadPriority; - t->threadName = threadName ? strdup(threadName) : NULL; - t->entryFunction = entryFunction; - t->userData = userData; - entryFunction = (android_thread_func_t)&thread_data_t::trampoline; - userData = t; - } -#endif - - if (threadStackSize) { - pthread_attr_setstacksize(&attr, threadStackSize); - } - - errno = 0; - pthread_t thread; - int result = pthread_create(&thread, &attr, - (android_pthread_entry)entryFunction, userData); - if (result != 0) { - LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n" - "(android threadPriority=%d)", - entryFunction, result, errno, threadPriority); - return 0; - } - - if (threadId != NULL) { - *threadId = (android_thread_id_t)thread; // XXX: this is not portable - } - return 1; -} - -android_thread_id_t androidGetThreadId() -{ - return (android_thread_id_t)pthread_self(); -} - -// ---------------------------------------------------------------------------- -#elif defined(HAVE_WIN32_THREADS) -#if 0 -#pragma mark - -#pragma mark WIN32_THREADS -#endif -// ---------------------------------------------------------------------------- - -/* - * Trampoline to make us __stdcall-compliant. - * - * We're expected to delete "vDetails" when we're done. - */ -struct threadDetails { - int (*func)(void*); - void* arg; -}; -static __stdcall unsigned int threadIntermediary(void* vDetails) -{ - struct threadDetails* pDetails = (struct threadDetails*) vDetails; - int result; - - result = (*(pDetails->func))(pDetails->arg); - - delete pDetails; - - LOG(LOG_VERBOSE, "thread", "thread exiting\n"); - return (unsigned int) result; -} - -/* - * Create and run a new thread. - */ -static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id) -{ - HANDLE hThread; - struct threadDetails* pDetails = new threadDetails; // must be on heap - unsigned int thrdaddr; - - pDetails->func = fn; - pDetails->arg = arg; - -#if defined(HAVE__BEGINTHREADEX) - hThread = (HANDLE) _beginthreadex(NULL, 0, threadIntermediary, pDetails, 0, - &thrdaddr); - if (hThread == 0) -#elif defined(HAVE_CREATETHREAD) - hThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) threadIntermediary, - (void*) pDetails, 0, (DWORD*) &thrdaddr); - if (hThread == NULL) -#endif - { - LOG(LOG_WARN, "thread", "WARNING: thread create failed\n"); - return false; - } - -#if defined(HAVE_CREATETHREAD) - /* close the management handle */ - CloseHandle(hThread); -#endif - - if (id != NULL) { - *id = (android_thread_id_t)thrdaddr; - } - - return true; -} - -int androidCreateRawThreadEtc(android_thread_func_t fn, - void *userData, - const char* threadName, - int32_t threadPriority, - size_t threadStackSize, - android_thread_id_t *threadId) -{ - return doCreateThread( fn, userData, threadId); -} - -android_thread_id_t androidGetThreadId() -{ - return (android_thread_id_t)GetCurrentThreadId(); -} - -// ---------------------------------------------------------------------------- -#else -#error "Threads not supported" -#endif - -// ---------------------------------------------------------------------------- - -#if 0 -#pragma mark - -#pragma mark Common Thread functions -#endif - -int androidCreateThread(android_thread_func_t fn, void* arg) -{ - return createThreadEtc(fn, arg); -} - -int androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id) -{ - return createThreadEtc(fn, arg, "android:unnamed_thread", - PRIORITY_DEFAULT, 0, id); -} - -static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc; - -int androidCreateThreadEtc(android_thread_func_t entryFunction, - void *userData, - const char* threadName, - int32_t threadPriority, - size_t threadStackSize, - android_thread_id_t *threadId) -{ - return gCreateThreadFn(entryFunction, userData, threadName, - threadPriority, threadStackSize, threadId); -} - -void androidSetCreateThreadFunc(android_create_thread_fn func) -{ - gCreateThreadFn = func; -} - -namespace android { - -/* - * =========================================================================== - * Mutex class - * =========================================================================== - */ - -#if 0 -#pragma mark - -#pragma mark Mutex -#endif - -#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX) -/* - * Simple pthread wrapper. - */ - -Mutex::Mutex() -{ - _init(); -} - -Mutex::Mutex(const char* name) -{ - // XXX: name not used for now - _init(); -} - -void Mutex::_init() -{ - pthread_mutex_t* pMutex = new pthread_mutex_t; - pthread_mutex_init(pMutex, NULL); - mState = pMutex; -} - -Mutex::~Mutex() -{ - delete (pthread_mutex_t*) mState; -} - -status_t Mutex::lock() -{ - int res; - while ((res=pthread_mutex_lock((pthread_mutex_t*) mState)) == EINTR) ; - return -res; -} - -void Mutex::unlock() -{ - pthread_mutex_unlock((pthread_mutex_t*) mState); -} - -status_t Mutex::tryLock() -{ - int res; - while ((res=pthread_mutex_trylock((pthread_mutex_t*) mState)) == EINTR) ; - return -res; -} - -#elif defined(HAVE_FUTEX) -#if 0 -#pragma mark - -#endif - -#define STATE ((futex_mutex_t*) (&mState)) - -Mutex::Mutex() -{ - _init(); -} - -Mutex::Mutex(const char* name) -{ - _init(); -} - -void -Mutex::_init() -{ - futex_mutex_init(STATE); -} - -Mutex::~Mutex() -{ -} - -status_t Mutex::lock() -{ - int res; - while ((res=futex_mutex_lock(STATE, FUTEX_WAIT_INFINITE)) == EINTR) ; - return -res; -} - -void Mutex::unlock() -{ - futex_mutex_unlock(STATE); -} - -status_t Mutex::tryLock() -{ - int res; - while ((res=futex_mutex_trylock(STATE)) == EINTR) ; - return -res; -} -#undef STATE - -#elif defined(HAVE_WIN32_THREADS) -#if 0 -#pragma mark - -#endif - -Mutex::Mutex() -{ - HANDLE hMutex; - - assert(sizeof(hMutex) == sizeof(mState)); - - hMutex = CreateMutex(NULL, FALSE, NULL); - mState = (void*) hMutex; -} - -Mutex::Mutex(const char* name) -{ - // XXX: name not used for now - HANDLE hMutex; - - hMutex = CreateMutex(NULL, FALSE, NULL); - mState = (void*) hMutex; -} - -Mutex::~Mutex() -{ - CloseHandle((HANDLE) mState); -} - -status_t Mutex::lock() -{ - DWORD dwWaitResult; - dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE); - return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR; -} - -void Mutex::unlock() -{ - if (!ReleaseMutex((HANDLE) mState)) - LOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n"); -} - -status_t Mutex::tryLock() -{ - DWORD dwWaitResult; - - dwWaitResult = WaitForSingleObject((HANDLE) mState, 0); - if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT) - LOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n"); - return (dwWaitResult == WAIT_OBJECT_0) ? 0 : -1; -} - -#else -#error "Somebody forgot to implement threads for this platform." -#endif - - -/* - * =========================================================================== - * Condition class - * =========================================================================== - */ - -#if 0 -#pragma mark - -#pragma mark Condition -#endif - -#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX) - -/* - * Constructor. This is a simple pthread wrapper. - */ -Condition::Condition() -{ - pthread_cond_t* pCond = new pthread_cond_t; - - pthread_cond_init(pCond, NULL); - mState = pCond; -} - -/* - * Destructor. - */ -Condition::~Condition() -{ - pthread_cond_destroy((pthread_cond_t*) mState); - delete (pthread_cond_t*) mState; -} - -/* - * Wait on a condition variable. Lock the mutex before calling. - */ - -status_t Condition::wait(Mutex& mutex) -{ - assert(mutex.mState != NULL); - - int cc; - while ((cc = pthread_cond_wait((pthread_cond_t*)mState, - (pthread_mutex_t*) mutex.mState)) == EINTR) ; - return -cc; -} - -status_t Condition::wait(Mutex& mutex, nsecs_t abstime) -{ - assert(mutex.mState != NULL); - - struct timespec ts; - ts.tv_sec = abstime/1000000000; - ts.tv_nsec = abstime-(ts.tv_sec*1000000000); - - int cc; - while ((cc = pthread_cond_timedwait((pthread_cond_t*)mState, - (pthread_mutex_t*) mutex.mState, &ts)) == EINTR) ; - return -cc; -} - -status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) -{ - return wait(mutex, systemTime()+reltime); -} - -/* - * Signal the condition variable, allowing one thread to continue. - */ -void Condition::signal() -{ - pthread_cond_signal((pthread_cond_t*) mState); -} - -/* - * Signal the condition variable, allowing all threads to continue. - */ -void Condition::broadcast() -{ - pthread_cond_broadcast((pthread_cond_t*) mState); -} - -#elif defined(HAVE_FUTEX) -#if 0 -#pragma mark - -#endif - -#define STATE ((futex_cond_t*) (&mState)) - -/* - * Constructor. This is a simple pthread wrapper. - */ -Condition::Condition() -{ - futex_cond_init(STATE); -} - -/* - * Destructor. - */ -Condition::~Condition() -{ -} - -/* - * Wait on a condition variable. Lock the mutex before calling. - */ - -status_t Condition::wait(Mutex& mutex) -{ - assert(mutex.mState != NULL); - - int res; - while ((res = futex_cond_wait(STATE, - (futex_mutex_t*)(&mutex.mState), FUTEX_WAIT_INFINITE)) == -EINTR) ; - - return -res; -} - -status_t Condition::wait(Mutex& mutex, nsecs_t abstime) -{ - nsecs_t reltime = abstime - systemTime(); - if (reltime <= 0) return true; - return waitRelative(mutex, reltime); -} - -status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) -{ - assert(mutex.mState != NULL); - int res; - unsigned msec = ns2ms(reltime); - if(msec == 0) - return true; - // This code will not time out at the correct time if interrupted by signals - while ((res = futex_cond_wait(STATE, - (futex_mutex_t*)(&mutex.mState), msec)) == -EINTR) ; - return res; -} - -/* - * Signal the condition variable, allowing one thread to continue. - */ -void Condition::signal() -{ - futex_cond_signal(STATE); -} - -/* - * Signal the condition variable, allowing all threads to continue. - */ -void Condition::broadcast() -{ - futex_cond_broadcast(STATE); -} - -#undef STATE - -#elif defined(HAVE_WIN32_THREADS) -#if 0 -#pragma mark - -#endif - -/* - * Windows doesn't have a condition variable solution. It's possible - * to create one, but it's easy to get it wrong. For a discussion, and - * the origin of this implementation, see: - * - * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html - * - * The implementation shown on the page does NOT follow POSIX semantics. - * As an optimization they require acquiring the external mutex before - * calling signal() and broadcast(), whereas POSIX only requires grabbing - * it before calling wait(). The implementation here has been un-optimized - * to have the correct behavior. - */ -typedef struct WinCondition { - // Number of waiting threads. - int waitersCount; - - // Serialize access to waitersCount. - CRITICAL_SECTION waitersCountLock; - - // Semaphore used to queue up threads waiting for the condition to - // become signaled. - HANDLE sema; - - // An auto-reset event used by the broadcast/signal thread to wait - // for all the waiting thread(s) to wake up and be released from - // the semaphore. - HANDLE waitersDone; - - // This mutex wouldn't be necessary if we required that the caller - // lock the external mutex before calling signal() and broadcast(). - // I'm trying to mimic pthread semantics though. - HANDLE internalMutex; - - // Keeps track of whether we were broadcasting or signaling. This - // allows us to optimize the code if we're just signaling. - bool wasBroadcast; - - status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime) - { - // Increment the wait count, avoiding race conditions. - EnterCriticalSection(&condState->waitersCountLock); - condState->waitersCount++; - //printf("+++ wait: incr waitersCount to %d (tid=%ld)\n", - // condState->waitersCount, getThreadId()); - LeaveCriticalSection(&condState->waitersCountLock); - - DWORD timeout = INFINITE; - if (abstime) { - nsecs_t reltime = *abstime - systemTime(); - if (reltime < 0) - reltime = 0; - timeout = reltime/1000000; - } - - // Atomically release the external mutex and wait on the semaphore. - DWORD res = - SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE); - - //printf("+++ wait: awake (tid=%ld)\n", getThreadId()); - - // Reacquire lock to avoid race conditions. - EnterCriticalSection(&condState->waitersCountLock); - - // No longer waiting. - condState->waitersCount--; - - // Check to see if we're the last waiter after a broadcast. - bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == 0); - - //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n", - // lastWaiter, condState->wasBroadcast, condState->waitersCount); - - LeaveCriticalSection(&condState->waitersCountLock); - - // If we're the last waiter thread during this particular broadcast - // then signal broadcast() that we're all awake. It'll drop the - // internal mutex. - if (lastWaiter) { - // Atomically signal the "waitersDone" event and wait until we - // can acquire the internal mutex. We want to do this in one step - // because it ensures that everybody is in the mutex FIFO before - // any thread has a chance to run. Without it, another thread - // could wake up, do work, and hop back in ahead of us. - SignalObjectAndWait(condState->waitersDone, condState->internalMutex, - INFINITE, FALSE); - } else { - // Grab the internal mutex. - WaitForSingleObject(condState->internalMutex, INFINITE); - } - - // Release the internal and grab the external. - ReleaseMutex(condState->internalMutex); - WaitForSingleObject(hMutex, INFINITE); - - return res == WAIT_OBJECT_0 ? NO_ERROR : -1; - } -} WinCondition; - -/* - * Constructor. Set up the WinCondition stuff. - */ -Condition::Condition() -{ - WinCondition* condState = new WinCondition; - - condState->waitersCount = 0; - condState->wasBroadcast = false; - // semaphore: no security, initial value of 0 - condState->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); - InitializeCriticalSection(&condState->waitersCountLock); - // auto-reset event, not signaled initially - condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL); - // used so we don't have to lock external mutex on signal/broadcast - condState->internalMutex = CreateMutex(NULL, FALSE, NULL); - - mState = condState; -} - -/* - * Destructor. Free Windows resources as well as our allocated storage. - */ -Condition::~Condition() -{ - WinCondition* condState = (WinCondition*) mState; - if (condState != NULL) { - CloseHandle(condState->sema); - CloseHandle(condState->waitersDone); - delete condState; - } -} - - -status_t Condition::wait(Mutex& mutex) -{ - WinCondition* condState = (WinCondition*) mState; - HANDLE hMutex = (HANDLE) mutex.mState; - - return ((WinCondition*)mState)->wait(condState, hMutex, NULL); -} - -status_t Condition::wait(Mutex& mutex, nsecs_t abstime) -{ - WinCondition* condState = (WinCondition*) mState; - HANDLE hMutex = (HANDLE) mutex.mState; - - return ((WinCondition*)mState)->wait(condState, hMutex, &abstime); -} - -status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) -{ - return wait(mutex, systemTime()+reltime); -} - -/* - * Signal the condition variable, allowing one thread to continue. - */ -void Condition::signal() -{ - WinCondition* condState = (WinCondition*) mState; - - // Lock the internal mutex. This ensures that we don't clash with - // broadcast(). - WaitForSingleObject(condState->internalMutex, INFINITE); - - EnterCriticalSection(&condState->waitersCountLock); - bool haveWaiters = (condState->waitersCount > 0); - LeaveCriticalSection(&condState->waitersCountLock); - - // If no waiters, then this is a no-op. Otherwise, knock the semaphore - // down a notch. - if (haveWaiters) - ReleaseSemaphore(condState->sema, 1, 0); - - // Release internal mutex. - ReleaseMutex(condState->internalMutex); -} - -/* - * Signal the condition variable, allowing all threads to continue. - * - * First we have to wake up all threads waiting on the semaphore, then - * we wait until all of the threads have actually been woken before - * releasing the internal mutex. This ensures that all threads are woken. - */ -void Condition::broadcast() -{ - WinCondition* condState = (WinCondition*) mState; - - // Lock the internal mutex. This keeps the guys we're waking up - // from getting too far. - WaitForSingleObject(condState->internalMutex, INFINITE); - - EnterCriticalSection(&condState->waitersCountLock); - bool haveWaiters = false; - - if (condState->waitersCount > 0) { - haveWaiters = true; - condState->wasBroadcast = true; - } - - if (haveWaiters) { - // Wake up all the waiters. - ReleaseSemaphore(condState->sema, condState->waitersCount, 0); - - LeaveCriticalSection(&condState->waitersCountLock); - - // Wait for all awakened threads to acquire the counting semaphore. - // The last guy who was waiting sets this. - WaitForSingleObject(condState->waitersDone, INFINITE); - - // Reset wasBroadcast. (No crit section needed because nobody - // else can wake up to poke at it.) - condState->wasBroadcast = 0; - } else { - // nothing to do - LeaveCriticalSection(&condState->waitersCountLock); - } - - // Release internal mutex. - ReleaseMutex(condState->internalMutex); -} - -#else -#error "condition variables not supported on this platform" -#endif - - -/* - * =========================================================================== - * ReadWriteLock class - * =========================================================================== - */ - -#if 0 -#pragma mark - -#pragma mark ReadWriteLock -#endif - -/* - * Add a reader. Readers are nice. They share. - */ -void ReadWriteLock::lockForRead() -{ - mLock.lock(); - while (mNumWriters > 0) { - LOG(LOG_DEBUG, "thread", "+++ lockForRead: waiting\n"); - mReadWaiter.wait(mLock); - } - assert(mNumWriters == 0); - mNumReaders++; -#if defined(PRINT_RENDER_TIMES) - if (mNumReaders == 1) - mDebugTimer.start(); -#endif - mLock.unlock(); -} - -/* - * Try to add a reader. If it doesn't work right away, return "false". - */ -bool ReadWriteLock::tryLockForRead() -{ - mLock.lock(); - if (mNumWriters > 0) { - mLock.unlock(); - return false; - } - assert(mNumWriters == 0); - mNumReaders++; -#if defined(PRINT_RENDER_TIMES) - if (mNumReaders == 1) - mDebugTimer.start(); -#endif - mLock.unlock(); - return true; -} - -/* - * Remove a reader. - */ -void ReadWriteLock::unlockForRead() -{ - mLock.lock(); - if (mNumReaders == 0) { - LOG(LOG_WARN, "thread", - "WARNING: unlockForRead requested, but not locked\n"); - return; - } - assert(mNumReaders > 0); - assert(mNumWriters == 0); - mNumReaders--; - if (mNumReaders == 0) { // last reader? -#if defined(PRINT_RENDER_TIMES) - mDebugTimer.stop(); - printf(" rdlk held %.3f msec\n", - (double) mDebugTimer.durationUsecs() / 1000.0); -#endif - //printf("+++ signaling writers (if any)\n"); - mWriteWaiter.signal(); // wake one writer (if any) - } - mLock.unlock(); -} - -/* - * Add a writer. This requires exclusive access to the object. - */ -void ReadWriteLock::lockForWrite() -{ - mLock.lock(); - while (mNumReaders > 0 || mNumWriters > 0) { - LOG(LOG_DEBUG, "thread", "+++ lockForWrite: waiting\n"); - mWriteWaiter.wait(mLock); - } - assert(mNumReaders == 0); - assert(mNumWriters == 0); - mNumWriters++; -#if defined(PRINT_RENDER_TIMES) - mDebugTimer.start(); -#endif - mLock.unlock(); -} - -/* - * Try to add a writer. If it doesn't work right away, return "false". - */ -bool ReadWriteLock::tryLockForWrite() -{ - mLock.lock(); - if (mNumReaders > 0 || mNumWriters > 0) { - mLock.unlock(); - return false; - } - assert(mNumReaders == 0); - assert(mNumWriters == 0); - mNumWriters++; -#if defined(PRINT_RENDER_TIMES) - mDebugTimer.start(); -#endif - mLock.unlock(); - return true; -} - -/* - * Remove a writer. - */ -void ReadWriteLock::unlockForWrite() -{ - mLock.lock(); - if (mNumWriters == 0) { - LOG(LOG_WARN, "thread", - "WARNING: unlockForWrite requested, but not locked\n"); - return; - } - assert(mNumWriters == 1); - mNumWriters--; -#if defined(PRINT_RENDER_TIMES) - mDebugTimer.stop(); - //printf(" wrlk held %.3f msec\n", - // (double) mDebugTimer.durationUsecs() / 1000.0); -#endif - // mWriteWaiter.signal(); // should other writers get first dibs? - //printf("+++ signaling readers (if any)\n"); - mReadWaiter.broadcast(); // wake all readers (if any) - mLock.unlock(); -} - -// ---------------------------------------------------------------------------- - -#if 0 -#pragma mark - -#pragma mark Thread::Thread -#endif - -/* - * This is our thread object! - */ - -Thread::Thread(bool canCallJava) - : mCanCallJava(canCallJava), - mThread(thread_id_t(-1)), - mLock("Thread::mLock"), - mStatus(NO_ERROR), - mExitPending(false), mRunning(false) -{ -} - -Thread::~Thread() -{ -} - -status_t Thread::readyToRun() -{ - return NO_ERROR; -} - -status_t Thread::run(const char* name, int32_t priority, size_t stack) -{ - Mutex::Autolock _l(mLock); - - if (mRunning) { - // thread already started - return INVALID_OPERATION; - } - - // reset status and exitPending to their default value, so we can - // try again after an error happened (either below, or in readyToRun()) - mStatus = NO_ERROR; - mExitPending = false; - mThread = thread_id_t(-1); - - // hold a strong reference on ourself - mHoldSelf = this; - - bool res; - if (mCanCallJava) { - res = createThreadEtc(_threadLoop, - this, name, priority, stack, &mThread); - } else { - res = androidCreateRawThreadEtc(_threadLoop, - this, name, priority, stack, &mThread); - } - - if (res == false) { - mStatus = UNKNOWN_ERROR; // something happened! - mRunning = false; - mThread = thread_id_t(-1); - } - - if (mStatus < 0) { - // something happened, don't leak - mHoldSelf.clear(); - } - - return mStatus; -} - -int Thread::_threadLoop(void* user) -{ - Thread* const self = static_cast<Thread*>(user); - sp<Thread> strong(self->mHoldSelf); - wp<Thread> weak(strong); - self->mHoldSelf.clear(); - - // we're about to run... - self->mStatus = self->readyToRun(); - if (self->mStatus!=NO_ERROR || self->mExitPending) { - // pretend the thread never started... - self->mExitPending = false; - self->mRunning = false; - return 0; - } - - // thread is running now - self->mRunning = true; - - do { - bool result = self->threadLoop(); - if (result == false || self->mExitPending) { - self->mExitPending = true; - self->mLock.lock(); - self->mRunning = false; - self->mThreadExitedCondition.signal(); - self->mLock.unlock(); - break; - } - - // Release our strong reference, to let a chance to the thread - // to die a peaceful death. - strong.clear(); - // And immediately, reacquire a strong reference for the next loop - strong = weak.promote(); - } while(strong != 0); - - return 0; -} - -void Thread::requestExit() -{ - mExitPending = true; -} - -status_t Thread::requestExitAndWait() -{ - if (mStatus == OK) { - - if (mThread == getThreadId()) { - LOGW( - "Thread (this=%p): don't call waitForExit() from this " - "Thread object's thread. It's a guaranteed deadlock!", - this); - return WOULD_BLOCK; - } - - requestExit(); - - Mutex::Autolock _l(mLock); - while (mRunning == true) { - mThreadExitedCondition.wait(mLock); - } - mExitPending = false; - } - return mStatus; -} - -bool Thread::exitPending() const -{ - return mExitPending; -} - - - -}; // namespace android diff --git a/libs/utils/TimerProbe.cpp b/libs/utils/TimerProbe.cpp deleted file mode 100644 index 835480d..0000000 --- a/libs/utils/TimerProbe.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/TimerProbe.h> - -#if ENABLE_TIMER_PROBE - -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "time" - -namespace android { - -Vector<TimerProbe::Bucket> TimerProbe::gBuckets; -TimerProbe* TimerProbe::gExecuteChain; -int TimerProbe::gIndent; -timespec TimerProbe::gRealBase; - -TimerProbe::TimerProbe(const char tag[], int* slot) : mTag(tag) -{ - mNext = gExecuteChain; - gExecuteChain = this; - mIndent = gIndent; - gIndent += 1; - if (mIndent > 0) { - if (*slot == 0) { - int count = gBuckets.add(); - *slot = count; - Bucket& bucket = gBuckets.editItemAt(count); - memset(&bucket, 0, sizeof(Bucket)); - bucket.mTag = tag; - bucket.mSlotPtr = slot; - bucket.mIndent = mIndent; - } - mBucket = *slot; - } - clock_gettime(CLOCK_REALTIME, &mRealStart); - if (gRealBase.tv_sec == 0) - gRealBase = mRealStart; - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mPStart); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &mTStart); -} - -void TimerProbe::end() -{ - timespec realEnd, pEnd, tEnd; - clock_gettime(CLOCK_REALTIME, &realEnd); - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &pEnd); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tEnd); - print(realEnd, pEnd, tEnd); - mTag = NULL; -} - -TimerProbe::~TimerProbe() -{ - if (mTag != NULL) - end(); - gExecuteChain = mNext; - gIndent--; -} - - -uint32_t TimerProbe::ElapsedTime(const timespec& start, const timespec& end) -{ - int sec = end.tv_sec - start.tv_sec; - int nsec = end.tv_nsec - start.tv_nsec; - if (nsec < 0) { - sec--; - nsec += 1000000000; - } - return sec * 1000000 + nsec / 1000; -} - -void TimerProbe::print(const timespec& r, const timespec& p, - const timespec& t) const -{ - uint32_t es = ElapsedTime(gRealBase, mRealStart); - uint32_t er = ElapsedTime(mRealStart, r); - uint32_t ep = ElapsedTime(mPStart, p); - uint32_t et = ElapsedTime(mTStart, t); - if (mIndent > 0) { - Bucket& bucket = gBuckets.editItemAt(mBucket); - if (bucket.mStart == 0) - bucket.mStart = es; - bucket.mReal += er; - bucket.mProcess += ep; - bucket.mThread += et; - bucket.mCount++; - return; - } - int index = 0; - int buckets = gBuckets.size(); - int count = 1; - const char* tag = mTag; - int indent = mIndent; - do { - LOGD("%-30.30s: (%3d) %-5.*s time=%-10.3f real=%7dus process=%7dus (%3d%%) thread=%7dus (%3d%%)\n", - tag, count, indent > 5 ? 5 : indent, "+++++", es / 1000000.0, - er, ep, ep * 100 / er, et, et * 100 / er); - if (index >= buckets) - break; - Bucket& bucket = gBuckets.editItemAt(index); - count = bucket.mCount; - es = bucket.mStart; - er = bucket.mReal; - ep = bucket.mProcess; - et = bucket.mThread; - tag = bucket.mTag; - indent = bucket.mIndent; - *bucket.mSlotPtr = 0; - } while (++index); // always true - gBuckets.clear(); -} - -}; // namespace android - -#endif diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp deleted file mode 100644 index 2abc811..0000000 --- a/libs/utils/Timers.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Timer functions. -// -#include <utils/Timers.h> -#include <utils/ported.h> // may need usleep -#include <utils/Log.h> - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <sys/time.h> -#include <time.h> -#include <errno.h> - -#ifdef HAVE_WIN32_THREADS -#include <windows.h> -#endif - -nsecs_t systemTime(int clock) -{ -#if defined(HAVE_POSIX_CLOCKS) - static const clockid_t clocks[] = { - CLOCK_REALTIME, - CLOCK_MONOTONIC, - CLOCK_PROCESS_CPUTIME_ID, - CLOCK_THREAD_CPUTIME_ID - }; - struct timespec t; - t.tv_sec = t.tv_nsec = 0; - clock_gettime(clocks[clock], &t); - return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec; -#else - // we don't support the clocks here. - struct timeval t; - t.tv_sec = t.tv_usec = 0; - gettimeofday(&t, NULL); - return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL; -#endif -} - -//#define MONITOR_USLEEP - -/* - * Sleep long enough that we'll wake up "interval" milliseconds after - * the previous snooze. - * - * The "nextTick" argument is updated on each call, and should be passed - * in every time. Set its fields to zero on the first call. - * - * Returns the #of intervals we have overslept, which will be zero if we're - * on time. [Currently just returns 0 or 1.] - */ -int sleepForInterval(long interval, struct timeval* pNextTick) -{ - struct timeval now; - long long timeBeforeNext; - long sleepTime = 0; - bool overSlept = false; - //int usleepBias = 0; - -#ifdef USLEEP_BIAS - /* - * Linux likes to add 9000ms or so. - * [not using this for now] - */ - //usleepBias = USLEEP_BIAS; -#endif - - gettimeofday(&now, NULL); - - if (pNextTick->tv_sec == 0) { - /* special-case for first time through */ - *pNextTick = now; - sleepTime = interval; - android::DurationTimer::addToTimeval(pNextTick, interval); - } else { - /* - * Compute how much time there is before the next tick. If this - * value is negative, we've run over. If we've run over a little - * bit we can shorten the next frame to keep the pace steady, but - * if we've dramatically overshot we need to re-sync. - */ - timeBeforeNext = android::DurationTimer::subtractTimevals(pNextTick, &now); - //printf("TOP: now=%ld.%ld next=%ld.%ld diff=%ld\n", - // now.tv_sec, now.tv_usec, pNextTick->tv_sec, pNextTick->tv_usec, - // (long) timeBeforeNext); - if (timeBeforeNext < -interval) { - /* way over */ - overSlept = true; - sleepTime = 0; - *pNextTick = now; - } else if (timeBeforeNext <= 0) { - /* slightly over, keep the pace steady */ - overSlept = true; - sleepTime = 0; - } else if (timeBeforeNext <= interval) { - /* right on schedule */ - sleepTime = timeBeforeNext; - } else if (timeBeforeNext > interval && timeBeforeNext <= 2*interval) { - /* sleep call returned early; do a longer sleep this time */ - sleepTime = timeBeforeNext; - } else if (timeBeforeNext > interval) { - /* we went back in time -- somebody updated system clock? */ - /* (could also be a *seriously* broken usleep()) */ - LOG(LOG_DEBUG, "", - " Impossible: timeBeforeNext = %ld\n", (long)timeBeforeNext); - sleepTime = 0; - *pNextTick = now; - } - android::DurationTimer::addToTimeval(pNextTick, interval); - } - //printf(" Before sleep: now=%ld.%ld next=%ld.%ld sleepTime=%ld\n", - // now.tv_sec, now.tv_usec, pNextTick->tv_sec, pNextTick->tv_usec, - // sleepTime); - - /* - * Sleep for the designated period of time. - * - * Linux tends to sleep for longer than requested, often by 17-18ms. - * MinGW tends to sleep for less than requested, by as much as 14ms, - * but occasionally oversleeps for 40+ms (looks like some external - * factors plus round-off on a 64Hz clock). Cygwin is pretty steady. - * - * If you start the MinGW version, and then launch the Cygwin version, - * the MinGW clock becomes more erratic. Not entirely sure why. - * - * (There's a lot of stuff here; it's really just a usleep() call with - * a bunch of instrumentation.) - */ - if (sleepTime > 0) { -#if defined(MONITOR_USLEEP) - struct timeval before, after; - long long actual; - - gettimeofday(&before, NULL); - usleep((long) sleepTime); - gettimeofday(&after, NULL); - - /* check usleep() accuracy; default Linux threads are pretty sloppy */ - actual = android::DurationTimer::subtractTimevals(&after, &before); - if ((long) actual < sleepTime - 14000 /*(sleepTime/10)*/ || - (long) actual > sleepTime + 20000 /*(sleepTime/10)*/) - { - LOG(LOG_DEBUG, "", " Odd usleep: req=%ld, actual=%ld\n", sleepTime, - (long) actual); - } -#else -#ifdef HAVE_WIN32_THREADS - Sleep( sleepTime/1000 ); -#else - usleep((long) sleepTime); -#endif -#endif - } - - //printf("slept %d\n", sleepTime); - - if (overSlept) - return 1; // close enough - else - return 0; -} - - -/* - * =========================================================================== - * DurationTimer - * =========================================================================== - */ - -using namespace android; - -// Start the timer. -void DurationTimer::start(void) -{ - gettimeofday(&mStartWhen, NULL); -} - -// Stop the timer. -void DurationTimer::stop(void) -{ - gettimeofday(&mStopWhen, NULL); -} - -// Get the duration in microseconds. -long long DurationTimer::durationUsecs(void) const -{ - return (long) subtractTimevals(&mStopWhen, &mStartWhen); -} - -// Subtract two timevals. Returns the difference (ptv1-ptv2) in -// microseconds. -/*static*/ long long DurationTimer::subtractTimevals(const struct timeval* ptv1, - const struct timeval* ptv2) -{ - long long stop = ((long long) ptv1->tv_sec) * 1000000LL + - ((long long) ptv1->tv_usec); - long long start = ((long long) ptv2->tv_sec) * 1000000LL + - ((long long) ptv2->tv_usec); - return stop - start; -} - -// Add the specified amount of time to the timeval. -/*static*/ void DurationTimer::addToTimeval(struct timeval* ptv, long usec) -{ - if (usec < 0) { - LOG(LOG_WARN, "", "Negative values not supported in addToTimeval\n"); - return; - } - - // normalize tv_usec if necessary - if (ptv->tv_usec >= 1000000) { - ptv->tv_sec += ptv->tv_usec / 1000000; - ptv->tv_usec %= 1000000; - } - - ptv->tv_usec += usec % 1000000; - if (ptv->tv_usec >= 1000000) { - ptv->tv_usec -= 1000000; - ptv->tv_sec++; - } - ptv->tv_sec += usec / 1000000; -} - diff --git a/libs/utils/Unicode.cpp b/libs/utils/Unicode.cpp deleted file mode 100644 index 33f535f..0000000 --- a/libs/utils/Unicode.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "utils/AndroidUnicode.h" -#include "characterData.h" - -#define LOG_TAG "Unicode" -#include "utils/Log.h" - -// ICU headers for using macros -#include <unicode/utf16.h> - -#define MIN_RADIX 2 -#define MAX_RADIX 36 - -#define TYPE_SHIFT 0 -#define TYPE_MASK ((1<<5)-1) - -#define DIRECTION_SHIFT (TYPE_SHIFT+5) -#define DIRECTION_MASK ((1<<5)-1) - -#define MIRRORED_SHIFT (DIRECTION_SHIFT+5) -#define MIRRORED_MASK ((1<<1)-1) - -#define TOUPPER_SHIFT (MIRRORED_SHIFT+1) -#define TOUPPER_MASK ((1<<6)-1) - -#define TOLOWER_SHIFT (TOUPPER_SHIFT+6) -#define TOLOWER_MASK ((1<<6)-1) - -#define TOTITLE_SHIFT (TOLOWER_SHIFT+6) -#define TOTITLE_MASK ((1<<2)-1) - -#define MIRROR_SHIFT (TOTITLE_SHIFT+2) -#define MIRROR_MASK ((1<<5)-1) - -#define NUMERIC_SHIFT (TOTITLE_SHIFT+2) -#define NUMERIC_MASK ((1<<7)-1) - -#define DECOMPOSITION_SHIFT (11) -#define DECOMPOSITION_MASK ((1<<5)-1) - -/* - * Returns the value stored in the CharacterData tables that contains - * an index into the packed data table and the decomposition type. - */ -static uint16_t findCharacterValue(UChar32 c) -{ - LOG_ASSERT(c >= 0 && c <= 0x10FFFF, "findCharacterValue received an invalid codepoint"); - if (c < 256) - return CharacterData::LATIN1_DATA[c]; - - // Rotate the bits because the tables are separated into even and odd codepoints - c = (c >> 1) | ((c & 1) << 20); - - CharacterData::Range search = CharacterData::FULL_DATA[c >> 16]; - const uint32_t* array = search.array; - - // This trick is so that that compare in the while loop does not - // need to shift the array entry down by 16 - c <<= 16; - c |= 0xFFFF; - - int high = (int)search.length - 1; - int low = 0; - - if (high < 0) - return 0; - - while (low < high - 1) - { - int probe = (high + low) >> 1; - - // The entries contain the codepoint in the high 16 bits and the index - // into PACKED_DATA in the low 16. - if (array[probe] > (unsigned)c) - high = probe; - else - low = probe; - } - - LOG_ASSERT((array[low] <= (unsigned)c), "A suitable range was not found"); - return array[low] & 0xFFFF; -} - -uint32_t android::Unicode::getPackedData(UChar32 c) -{ - // findCharacterValue returns a 16-bit value with the top 5 bits containing a decomposition type - // and the remaining bits containing an index. - return CharacterData::PACKED_DATA[findCharacterValue(c) & 0x7FF]; -} - -android::Unicode::CharType android::Unicode::getType(UChar32 c) -{ - if (c < 0 || c >= 0x10FFFF) - return CHARTYPE_UNASSIGNED; - return (CharType)((getPackedData(c) >> TYPE_SHIFT) & TYPE_MASK); -} - -android::Unicode::DecompositionType android::Unicode::getDecompositionType(UChar32 c) -{ - // findCharacterValue returns a 16-bit value with the top 5 bits containing a decomposition type - // and the remaining bits containing an index. - return (DecompositionType)((findCharacterValue(c) >> DECOMPOSITION_SHIFT) & DECOMPOSITION_MASK); -} - -int android::Unicode::getDigitValue(UChar32 c, int radix) -{ - if (radix < MIN_RADIX || radix > MAX_RADIX) - return -1; - - int tempValue = radix; - - if (c >= '0' && c <= '9') - tempValue = c - '0'; - else if (c >= 'a' && c <= 'z') - tempValue = c - 'a' + 10; - else if (c >= 'A' && c <= 'Z') - tempValue = c - 'A' + 10; - - return tempValue < radix ? tempValue : -1; -} - -int android::Unicode::getNumericValue(UChar32 c) -{ - if (isMirrored(c)) - return -1; - - return (int) CharacterData::NUMERICS[((getPackedData(c) >> NUMERIC_SHIFT) & NUMERIC_MASK)]; -} - -UChar32 android::Unicode::toLower(UChar32 c) -{ - return c + CharacterData::LCDIFF[(getPackedData(c) >> TOLOWER_SHIFT) & TOLOWER_MASK]; -} - -UChar32 android::Unicode::toUpper(UChar32 c) -{ - return c + CharacterData::UCDIFF[(getPackedData(c) >> TOUPPER_SHIFT) & TOUPPER_MASK]; -} - -android::Unicode::Direction android::Unicode::getDirectionality(UChar32 c) -{ - uint32_t data = getPackedData(c); - - if (0 == data) - return DIRECTIONALITY_UNDEFINED; - - Direction d = (Direction) ((data >> DIRECTION_SHIFT) & DIRECTION_MASK); - - if (DIRECTION_MASK == d) - return DIRECTIONALITY_UNDEFINED; - - return d; -} - -bool android::Unicode::isMirrored(UChar32 c) -{ - return ((getPackedData(c) >> MIRRORED_SHIFT) & MIRRORED_MASK) != 0; -} - -UChar32 android::Unicode::toMirror(UChar32 c) -{ - if (!isMirrored(c)) - return c; - - return c + CharacterData::MIRROR_DIFF[(getPackedData(c) >> MIRROR_SHIFT) & MIRROR_MASK]; -} - -UChar32 android::Unicode::toTitle(UChar32 c) -{ - int32_t diff = CharacterData::TCDIFF[(getPackedData(c) >> TOTITLE_SHIFT) & TOTITLE_MASK]; - - if (TOTITLE_MASK == diff) - return toUpper(c); - - return c + diff; -} - - diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp deleted file mode 100644 index 2c2d667..0000000 --- a/libs/utils/VectorImpl.cpp +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Vector" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include <utils/Log.h> -#include <utils/Errors.h> -#include <utils/SharedBuffer.h> -#include <utils/VectorImpl.h> - -/*****************************************************************************/ - - -namespace android { - -// ---------------------------------------------------------------------------- - -const size_t kMinVectorCapacity = 4; - -static inline size_t max(size_t a, size_t b) { - return a>b ? a : b; -} - -// ---------------------------------------------------------------------------- - -VectorImpl::VectorImpl(size_t itemSize, uint32_t flags) - : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize) -{ -} - -VectorImpl::VectorImpl(const VectorImpl& rhs) - : mStorage(rhs.mStorage), mCount(rhs.mCount), - mFlags(rhs.mFlags), mItemSize(rhs.mItemSize) -{ - if (mStorage) { - SharedBuffer::sharedBuffer(mStorage)->acquire(); - } -} - -VectorImpl::~VectorImpl() -{ - LOG_ASSERT(!mCount, - "[%p] " - "subclasses of VectorImpl must call finish_vector()" - " in their destructor. Leaking %d bytes.", - this, (int)(mCount*mItemSize)); - // We can't call _do_destroy() here because the vtable is already gone. -} - -VectorImpl& VectorImpl::operator = (const VectorImpl& rhs) -{ - LOG_ASSERT(mItemSize == rhs.mItemSize, - "Vector<> have different types (this=%p, rhs=%p)", this, &rhs); - if (this != &rhs) { - release_storage(); - if (rhs.mCount) { - mStorage = rhs.mStorage; - mCount = rhs.mCount; - SharedBuffer::sharedBuffer(mStorage)->acquire(); - } else { - mStorage = 0; - mCount = 0; - } - } - return *this; -} - -void* VectorImpl::editArrayImpl() -{ - if (mStorage) { - SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage)->attemptEdit(); - if (sb == 0) { - sb = SharedBuffer::alloc(capacity() * mItemSize); - if (sb) { - _do_copy(sb->data(), mStorage, mCount); - release_storage(); - mStorage = sb->data(); - } - } - } - return mStorage; -} - -size_t VectorImpl::capacity() const -{ - if (mStorage) { - return SharedBuffer::sharedBuffer(mStorage)->size() / mItemSize; - } - return 0; -} - -ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index) -{ - if (index > size()) - return BAD_INDEX; - void* where = _grow(index, vector.size()); - if (where) { - _do_copy(where, vector.arrayImpl(), vector.size()); - } - return where ? index : (ssize_t)NO_MEMORY; -} - -ssize_t VectorImpl::appendVector(const VectorImpl& vector) -{ - return insertVectorAt(vector, size()); -} - -ssize_t VectorImpl::insertAt(size_t index, size_t numItems) -{ - return insertAt(0, index, numItems); -} - -ssize_t VectorImpl::insertAt(const void* item, size_t index, size_t numItems) -{ - if (index > size()) - return BAD_INDEX; - void* where = _grow(index, numItems); - if (where) { - if (item) { - _do_splat(where, item, numItems); - } else { - _do_construct(where, numItems); - } - } - return where ? index : (ssize_t)NO_MEMORY; -} - -static int sortProxy(const void* lhs, const void* rhs, void* func) -{ - return (*(VectorImpl::compar_t)func)(lhs, rhs); -} - -status_t VectorImpl::sort(VectorImpl::compar_t cmp) -{ - return sort(sortProxy, (void*)cmp); -} - -status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state) -{ - // the sort must be stable. we're using insertion sort which - // is well suited for small and already sorted arrays - // for big arrays, it could be better to use mergesort - const ssize_t count = size(); - if (count > 1) { - void* array = const_cast<void*>(arrayImpl()); - void* temp = 0; - ssize_t i = 1; - while (i < count) { - void* item = reinterpret_cast<char*>(array) + mItemSize*(i); - void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1); - if (cmp(curr, item, state) > 0) { - - if (!temp) { - // we're going to have to modify the array... - array = editArrayImpl(); - if (!array) return NO_MEMORY; - temp = malloc(mItemSize); - if (!temp) return NO_MEMORY; - _do_construct(temp, 1); - item = reinterpret_cast<char*>(array) + mItemSize*(i); - curr = reinterpret_cast<char*>(array) + mItemSize*(i-1); - } - - _do_copy(temp, item, 1); - - ssize_t j = i-1; - void* next = reinterpret_cast<char*>(array) + mItemSize*(i); - do { - _do_copy(next, curr, 1); - next = curr; - --j; - curr = reinterpret_cast<char*>(array) + mItemSize*(j); - } while (j>=0 && (cmp(curr, temp, state) > 0)); - - _do_copy(next, temp, 1); - } - i++; - } - - if (temp) { - _do_destroy(temp, 1); - free(temp); - } - } - return NO_ERROR; -} - -void VectorImpl::pop() -{ - if (size()) - removeItemsAt(size()-1, 1); -} - -void VectorImpl::push() -{ - push(0); -} - -void VectorImpl::push(const void* item) -{ - insertAt(item, size()); -} - -ssize_t VectorImpl::add() -{ - return add(0); -} - -ssize_t VectorImpl::add(const void* item) -{ - return insertAt(item, size()); -} - -ssize_t VectorImpl::replaceAt(size_t index) -{ - return replaceAt(0, index); -} - -ssize_t VectorImpl::replaceAt(const void* prototype, size_t index) -{ - LOG_ASSERT(index<size(), - "[%p] replace: index=%d, size=%d", this, (int)index, (int)size()); - - void* item = editItemLocation(index); - if (item == 0) - return NO_MEMORY; - _do_destroy(item, 1); - if (prototype == 0) { - _do_construct(item, 1); - } else { - _do_copy(item, prototype, 1); - } - return ssize_t(index); -} - -ssize_t VectorImpl::removeItemsAt(size_t index, size_t count) -{ - LOG_ASSERT((index+count)<=size(), - "[%p] remove: index=%d, count=%d, size=%d", - this, (int)index, (int)count, (int)size()); - - if ((index+count) > size()) - return BAD_VALUE; - _shrink(index, count); - return index; -} - -void VectorImpl::finish_vector() -{ - release_storage(); - mStorage = 0; - mCount = 0; -} - -void VectorImpl::clear() -{ - _shrink(0, mCount); -} - -void* VectorImpl::editItemLocation(size_t index) -{ - LOG_ASSERT(index<capacity(), - "[%p] itemLocation: index=%d, capacity=%d, count=%d", - this, (int)index, (int)capacity(), (int)mCount); - - void* buffer = editArrayImpl(); - if (buffer) - return reinterpret_cast<char*>(buffer) + index*mItemSize; - return 0; -} - -const void* VectorImpl::itemLocation(size_t index) const -{ - LOG_ASSERT(index<capacity(), - "[%p] editItemLocation: index=%d, capacity=%d, count=%d", - this, (int)index, (int)capacity(), (int)mCount); - - const void* buffer = arrayImpl(); - if (buffer) - return reinterpret_cast<const char*>(buffer) + index*mItemSize; - return 0; -} - -ssize_t VectorImpl::setCapacity(size_t new_capacity) -{ - size_t current_capacity = capacity(); - ssize_t amount = new_capacity - size(); - if (amount <= 0) { - // we can't reduce the capacity - return current_capacity; - } - SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize); - if (sb) { - void* array = sb->data(); - _do_copy(array, mStorage, size()); - release_storage(); - mStorage = const_cast<void*>(array); - } else { - return NO_MEMORY; - } - return new_capacity; -} - -void VectorImpl::release_storage() -{ - if (mStorage) { - const SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage); - if (sb->release(SharedBuffer::eKeepStorage) == 1) { - _do_destroy(mStorage, mCount); - SharedBuffer::dealloc(sb); - } - } -} - -void* VectorImpl::_grow(size_t where, size_t amount) -{ -// LOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d", -// this, (int)where, (int)amount, (int)mCount, (int)capacity()); - - if (where > mCount) - where = mCount; - - const size_t new_size = mCount + amount; - if (capacity() < new_size) { - const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2); -// LOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity); - if ((mStorage) && - (mCount==where) && - (mFlags & HAS_TRIVIAL_COPY) && - (mFlags & HAS_TRIVIAL_DTOR)) - { - const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage); - SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize); - mStorage = sb->data(); - } else { - SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize); - if (sb) { - void* array = sb->data(); - if (where>0) { - _do_copy(array, mStorage, where); - } - if (mCount>where) { - const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize; - void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; - _do_copy(dest, from, mCount-where); - } - release_storage(); - mStorage = const_cast<void*>(array); - } - } - } else { - ssize_t s = mCount-where; - if (s>0) { - void* array = editArrayImpl(); - void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; - const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize; - _do_move_forward(to, from, s); - } - } - mCount += amount; - void* free_space = const_cast<void*>(itemLocation(where)); - return free_space; -} - -void VectorImpl::_shrink(size_t where, size_t amount) -{ - if (!mStorage) - return; - -// LOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d", -// this, (int)where, (int)amount, (int)mCount, (int)capacity()); - - if (where >= mCount) - where = mCount - amount; - - const size_t new_size = mCount - amount; - if (new_size*3 < capacity()) { - const size_t new_capacity = max(kMinVectorCapacity, new_size*2); -// LOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity); - if ((where == mCount-amount) && - (mFlags & HAS_TRIVIAL_COPY) && - (mFlags & HAS_TRIVIAL_DTOR)) - { - const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage); - SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize); - mStorage = sb->data(); - } else { - SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize); - if (sb) { - void* array = sb->data(); - if (where>0) { - _do_copy(array, mStorage, where); - } - if (mCount > where+amount) { - const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize; - void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize; - _do_copy(dest, from, mCount-(where+amount)); - } - release_storage(); - mStorage = const_cast<void*>(array); - } - } - } else { - void* array = editArrayImpl(); - void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize; - _do_destroy(to, amount); - ssize_t s = mCount-(where+amount); - if (s>0) { - const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; - _do_move_backward(to, from, s); - } - } - - // adjust the number of items... - mCount -= amount; -} - -size_t VectorImpl::itemSize() const { - return mItemSize; -} - -void VectorImpl::_do_construct(void* storage, size_t num) const -{ - if (!(mFlags & HAS_TRIVIAL_CTOR)) { - do_construct(storage, num); - } -} - -void VectorImpl::_do_destroy(void* storage, size_t num) const -{ - if (!(mFlags & HAS_TRIVIAL_DTOR)) { - do_destroy(storage, num); - } -} - -void VectorImpl::_do_copy(void* dest, const void* from, size_t num) const -{ - if (!(mFlags & HAS_TRIVIAL_COPY)) { - do_copy(dest, from, num); - } else { - memcpy(dest, from, num*itemSize()); - } -} - -void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const { - do_splat(dest, item, num); -} - -void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const { - do_move_forward(dest, from, num); -} - -void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const { - do_move_backward(dest, from, num); -} - -void VectorImpl::reservedVectorImpl1() { } -void VectorImpl::reservedVectorImpl2() { } -void VectorImpl::reservedVectorImpl3() { } -void VectorImpl::reservedVectorImpl4() { } -void VectorImpl::reservedVectorImpl5() { } -void VectorImpl::reservedVectorImpl6() { } -void VectorImpl::reservedVectorImpl7() { } -void VectorImpl::reservedVectorImpl8() { } - -/*****************************************************************************/ - -SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags) - : VectorImpl(itemSize, flags) -{ -} - -SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs) -: VectorImpl(rhs) -{ -} - -SortedVectorImpl::~SortedVectorImpl() -{ -} - -SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs) -{ - return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) ); -} - -ssize_t SortedVectorImpl::indexOf(const void* item) const -{ - return _indexOrderOf(item); -} - -size_t SortedVectorImpl::orderOf(const void* item) const -{ - size_t o; - _indexOrderOf(item, &o); - return o; -} - -ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const -{ - // binary search - ssize_t err = NAME_NOT_FOUND; - ssize_t l = 0; - ssize_t h = size()-1; - ssize_t mid; - const void* a = arrayImpl(); - const size_t s = itemSize(); - while (l <= h) { - mid = l + (h - l)/2; - const void* const curr = reinterpret_cast<const char *>(a) + (mid*s); - const int c = do_compare(curr, item); - if (c == 0) { - err = l = mid; - break; - } else if (c < 0) { - l = mid + 1; - } else { - h = mid - 1; - } - } - if (order) *order = l; - return err; -} - -ssize_t SortedVectorImpl::add(const void* item) -{ - size_t order; - ssize_t index = _indexOrderOf(item, &order); - if (index < 0) { - index = VectorImpl::insertAt(item, order, 1); - } else { - index = VectorImpl::replaceAt(item, index); - } - return index; -} - -ssize_t SortedVectorImpl::merge(const VectorImpl& vector) -{ - // naive merge... - if (!vector.isEmpty()) { - const void* buffer = vector.arrayImpl(); - const size_t is = itemSize(); - size_t s = vector.size(); - for (size_t i=0 ; i<s ; i++) { - ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is ); - if (err<0) { - return err; - } - } - } - return NO_ERROR; -} - -ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector) -{ - // we've merging a sorted vector... nice! - ssize_t err = NO_ERROR; - if (!vector.isEmpty()) { - // first take care of the case where the vectors are sorted together - if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) { - err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0); - } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) { - err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector)); - } else { - // this could be made a little better - err = merge(static_cast<const VectorImpl&>(vector)); - } - } - return err; -} - -ssize_t SortedVectorImpl::remove(const void* item) -{ - ssize_t i = indexOf(item); - if (i>=0) { - VectorImpl::removeItemsAt(i, 1); - } - return i; -} - -void SortedVectorImpl::reservedSortedVectorImpl1() { }; -void SortedVectorImpl::reservedSortedVectorImpl2() { }; -void SortedVectorImpl::reservedSortedVectorImpl3() { }; -void SortedVectorImpl::reservedSortedVectorImpl4() { }; -void SortedVectorImpl::reservedSortedVectorImpl5() { }; -void SortedVectorImpl::reservedSortedVectorImpl6() { }; -void SortedVectorImpl::reservedSortedVectorImpl7() { }; -void SortedVectorImpl::reservedSortedVectorImpl8() { }; - - -/*****************************************************************************/ - -}; // namespace android - diff --git a/libs/utils/ZipEntry.cpp b/libs/utils/ZipEntry.cpp deleted file mode 100644 index fbc9e67..0000000 --- a/libs/utils/ZipEntry.cpp +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Access to entries in a Zip archive. -// - -#define LOG_TAG "zip" - -#include "utils/ZipEntry.h" -#include "utils/Log.h" - -#include <stdio.h> -#include <string.h> -#include <assert.h> - -using namespace android; - -/* - * Initialize a new ZipEntry structure from a FILE* positioned at a - * CentralDirectoryEntry. - * - * On exit, the file pointer will be at the start of the next CDE or - * at the EOCD. - */ -status_t ZipEntry::initFromCDE(FILE* fp) -{ - status_t result; - long posn; - bool hasDD; - - //LOGV("initFromCDE ---\n"); - - /* read the CDE */ - result = mCDE.read(fp); - if (result != NO_ERROR) { - LOGD("mCDE.read failed\n"); - return result; - } - - //mCDE.dump(); - - /* using the info in the CDE, go load up the LFH */ - posn = ftell(fp); - if (fseek(fp, mCDE.mLocalHeaderRelOffset, SEEK_SET) != 0) { - LOGD("local header seek failed (%ld)\n", - mCDE.mLocalHeaderRelOffset); - return UNKNOWN_ERROR; - } - - result = mLFH.read(fp); - if (result != NO_ERROR) { - LOGD("mLFH.read failed\n"); - return result; - } - - if (fseek(fp, posn, SEEK_SET) != 0) - return UNKNOWN_ERROR; - - //mLFH.dump(); - - /* - * We *might* need to read the Data Descriptor at this point and - * integrate it into the LFH. If this bit is set, the CRC-32, - * compressed size, and uncompressed size will be zero. In practice - * these seem to be rare. - */ - hasDD = (mLFH.mGPBitFlag & kUsesDataDescr) != 0; - if (hasDD) { - // do something clever - //LOGD("+++ has data descriptor\n"); - } - - /* - * Sanity-check the LFH. Note that this will fail if the "kUsesDataDescr" - * flag is set, because the LFH is incomplete. (Not a problem, since we - * prefer the CDE values.) - */ - if (!hasDD && !compareHeaders()) { - LOGW("WARNING: header mismatch\n"); - // keep going? - } - - /* - * If the mVersionToExtract is greater than 20, we may have an - * issue unpacking the record -- could be encrypted, compressed - * with something we don't support, or use Zip64 extensions. We - * can defer worrying about that to when we're extracting data. - */ - - return NO_ERROR; -} - -/* - * Initialize a new entry. Pass in the file name and an optional comment. - * - * Initializes the CDE and the LFH. - */ -void ZipEntry::initNew(const char* fileName, const char* comment) -{ - assert(fileName != NULL && *fileName != '\0'); // name required - - /* most fields are properly initialized by constructor */ - mCDE.mVersionMadeBy = kDefaultMadeBy; - mCDE.mVersionToExtract = kDefaultVersion; - mCDE.mCompressionMethod = kCompressStored; - mCDE.mFileNameLength = strlen(fileName); - if (comment != NULL) - mCDE.mFileCommentLength = strlen(comment); - mCDE.mExternalAttrs = 0x81b60020; // matches what WinZip does - - if (mCDE.mFileNameLength > 0) { - mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1]; - strcpy((char*) mCDE.mFileName, fileName); - } - if (mCDE.mFileCommentLength > 0) { - /* TODO: stop assuming null-terminated ASCII here? */ - mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1]; - strcpy((char*) mCDE.mFileComment, comment); - } - - copyCDEtoLFH(); -} - -/* - * Initialize a new entry, starting with the ZipEntry from a different - * archive. - * - * Initializes the CDE and the LFH. - */ -status_t ZipEntry::initFromExternal(const ZipFile* pZipFile, - const ZipEntry* pEntry) -{ - /* - * Copy everything in the CDE over, then fix up the hairy bits. - */ - memcpy(&mCDE, &pEntry->mCDE, sizeof(mCDE)); - - if (mCDE.mFileNameLength > 0) { - mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1]; - if (mCDE.mFileName == NULL) - return NO_MEMORY; - strcpy((char*) mCDE.mFileName, (char*)pEntry->mCDE.mFileName); - } - if (mCDE.mFileCommentLength > 0) { - mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1]; - if (mCDE.mFileComment == NULL) - return NO_MEMORY; - strcpy((char*) mCDE.mFileComment, (char*)pEntry->mCDE.mFileComment); - } - if (mCDE.mExtraFieldLength > 0) { - /* we null-terminate this, though it may not be a string */ - mCDE.mExtraField = new unsigned char[mCDE.mExtraFieldLength+1]; - if (mCDE.mExtraField == NULL) - return NO_MEMORY; - memcpy(mCDE.mExtraField, pEntry->mCDE.mExtraField, - mCDE.mExtraFieldLength+1); - } - - /* construct the LFH from the CDE */ - copyCDEtoLFH(); - - /* - * The LFH "extra" field is independent of the CDE "extra", so we - * handle it here. - */ - assert(mLFH.mExtraField == NULL); - mLFH.mExtraFieldLength = pEntry->mLFH.mExtraFieldLength; - if (mLFH.mExtraFieldLength > 0) { - mLFH.mExtraField = new unsigned char[mLFH.mExtraFieldLength+1]; - if (mLFH.mExtraField == NULL) - return NO_MEMORY; - memcpy(mLFH.mExtraField, pEntry->mLFH.mExtraField, - mLFH.mExtraFieldLength+1); - } - - return NO_ERROR; -} - -/* - * Insert pad bytes in the LFH by tweaking the "extra" field. This will - * potentially confuse something that put "extra" data in here earlier, - * but I can't find an actual problem. - */ -status_t ZipEntry::addPadding(int padding) -{ - if (padding <= 0) - return INVALID_OPERATION; - - //LOGI("HEY: adding %d pad bytes to existing %d in %s\n", - // padding, mLFH.mExtraFieldLength, mCDE.mFileName); - - if (mLFH.mExtraFieldLength > 0) { - /* extend existing field */ - unsigned char* newExtra; - - newExtra = new unsigned char[mLFH.mExtraFieldLength + padding]; - if (newExtra == NULL) - return NO_MEMORY; - memset(newExtra + mLFH.mExtraFieldLength, 0, padding); - memcpy(newExtra, mLFH.mExtraField, mLFH.mExtraFieldLength); - - delete[] mLFH.mExtraField; - mLFH.mExtraField = newExtra; - mLFH.mExtraFieldLength += padding; - } else { - /* create new field */ - mLFH.mExtraField = new unsigned char[padding]; - memset(mLFH.mExtraField, 0, padding); - mLFH.mExtraFieldLength = padding; - } - - return NO_ERROR; -} - -/* - * Set the fields in the LFH equal to the corresponding fields in the CDE. - * - * This does not touch the LFH "extra" field. - */ -void ZipEntry::copyCDEtoLFH(void) -{ - mLFH.mVersionToExtract = mCDE.mVersionToExtract; - mLFH.mGPBitFlag = mCDE.mGPBitFlag; - mLFH.mCompressionMethod = mCDE.mCompressionMethod; - mLFH.mLastModFileTime = mCDE.mLastModFileTime; - mLFH.mLastModFileDate = mCDE.mLastModFileDate; - mLFH.mCRC32 = mCDE.mCRC32; - mLFH.mCompressedSize = mCDE.mCompressedSize; - mLFH.mUncompressedSize = mCDE.mUncompressedSize; - mLFH.mFileNameLength = mCDE.mFileNameLength; - // the "extra field" is independent - - delete[] mLFH.mFileName; - if (mLFH.mFileNameLength > 0) { - mLFH.mFileName = new unsigned char[mLFH.mFileNameLength+1]; - strcpy((char*) mLFH.mFileName, (const char*) mCDE.mFileName); - } else { - mLFH.mFileName = NULL; - } -} - -/* - * Set some information about a file after we add it. - */ -void ZipEntry::setDataInfo(long uncompLen, long compLen, unsigned long crc32, - int compressionMethod) -{ - mCDE.mCompressionMethod = compressionMethod; - mCDE.mCRC32 = crc32; - mCDE.mCompressedSize = compLen; - mCDE.mUncompressedSize = uncompLen; - mCDE.mCompressionMethod = compressionMethod; - if (compressionMethod == kCompressDeflated) { - mCDE.mGPBitFlag |= 0x0002; // indicates maximum compression used - } - copyCDEtoLFH(); -} - -/* - * See if the data in mCDE and mLFH match up. This is mostly useful for - * debugging these classes, but it can be used to identify damaged - * archives. - * - * Returns "false" if they differ. - */ -bool ZipEntry::compareHeaders(void) const -{ - if (mCDE.mVersionToExtract != mLFH.mVersionToExtract) { - LOGV("cmp: VersionToExtract\n"); - return false; - } - if (mCDE.mGPBitFlag != mLFH.mGPBitFlag) { - LOGV("cmp: GPBitFlag\n"); - return false; - } - if (mCDE.mCompressionMethod != mLFH.mCompressionMethod) { - LOGV("cmp: CompressionMethod\n"); - return false; - } - if (mCDE.mLastModFileTime != mLFH.mLastModFileTime) { - LOGV("cmp: LastModFileTime\n"); - return false; - } - if (mCDE.mLastModFileDate != mLFH.mLastModFileDate) { - LOGV("cmp: LastModFileDate\n"); - return false; - } - if (mCDE.mCRC32 != mLFH.mCRC32) { - LOGV("cmp: CRC32\n"); - return false; - } - if (mCDE.mCompressedSize != mLFH.mCompressedSize) { - LOGV("cmp: CompressedSize\n"); - return false; - } - if (mCDE.mUncompressedSize != mLFH.mUncompressedSize) { - LOGV("cmp: UncompressedSize\n"); - return false; - } - if (mCDE.mFileNameLength != mLFH.mFileNameLength) { - LOGV("cmp: FileNameLength\n"); - return false; - } -#if 0 // this seems to be used for padding, not real data - if (mCDE.mExtraFieldLength != mLFH.mExtraFieldLength) { - LOGV("cmp: ExtraFieldLength\n"); - return false; - } -#endif - if (mCDE.mFileName != NULL) { - if (strcmp((char*) mCDE.mFileName, (char*) mLFH.mFileName) != 0) { - LOGV("cmp: FileName\n"); - return false; - } - } - - return true; -} - - -/* - * Convert the DOS date/time stamp into a UNIX time stamp. - */ -time_t ZipEntry::getModWhen(void) const -{ - struct tm parts; - - parts.tm_sec = (mCDE.mLastModFileTime & 0x001f) << 1; - parts.tm_min = (mCDE.mLastModFileTime & 0x07e0) >> 5; - parts.tm_hour = (mCDE.mLastModFileTime & 0xf800) >> 11; - parts.tm_mday = (mCDE.mLastModFileDate & 0x001f); - parts.tm_mon = ((mCDE.mLastModFileDate & 0x01e0) >> 5) -1; - parts.tm_year = ((mCDE.mLastModFileDate & 0xfe00) >> 9) + 80; - parts.tm_wday = parts.tm_yday = 0; - parts.tm_isdst = -1; // DST info "not available" - - return mktime(&parts); -} - -/* - * Set the CDE/LFH timestamp from UNIX time. - */ -void ZipEntry::setModWhen(time_t when) -{ -#ifdef HAVE_LOCALTIME_R - struct tm tmResult; -#endif - time_t even; - unsigned short zdate, ztime; - - struct tm* ptm; - - /* round up to an even number of seconds */ - even = (time_t)(((unsigned long)(when) + 1) & (~1)); - - /* expand */ -#ifdef HAVE_LOCALTIME_R - ptm = localtime_r(&even, &tmResult); -#else - ptm = localtime(&even); -#endif - - int year; - year = ptm->tm_year; - if (year < 80) - year = 80; - - zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday; - ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1; - - mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime; - mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate; -} - - -/* - * =========================================================================== - * ZipEntry::LocalFileHeader - * =========================================================================== - */ - -/* - * Read a local file header. - * - * On entry, "fp" points to the signature at the start of the header. - * On exit, "fp" points to the start of data. - */ -status_t ZipEntry::LocalFileHeader::read(FILE* fp) -{ - status_t result = NO_ERROR; - unsigned char buf[kLFHLen]; - - assert(mFileName == NULL); - assert(mExtraField == NULL); - - if (fread(buf, 1, kLFHLen, fp) != kLFHLen) { - result = UNKNOWN_ERROR; - goto bail; - } - - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) { - LOGD("whoops: didn't find expected signature\n"); - result = UNKNOWN_ERROR; - goto bail; - } - - mVersionToExtract = ZipEntry::getShortLE(&buf[0x04]); - mGPBitFlag = ZipEntry::getShortLE(&buf[0x06]); - mCompressionMethod = ZipEntry::getShortLE(&buf[0x08]); - mLastModFileTime = ZipEntry::getShortLE(&buf[0x0a]); - mLastModFileDate = ZipEntry::getShortLE(&buf[0x0c]); - mCRC32 = ZipEntry::getLongLE(&buf[0x0e]); - mCompressedSize = ZipEntry::getLongLE(&buf[0x12]); - mUncompressedSize = ZipEntry::getLongLE(&buf[0x16]); - mFileNameLength = ZipEntry::getShortLE(&buf[0x1a]); - mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1c]); - - // TODO: validate sizes - - /* grab filename */ - if (mFileNameLength != 0) { - mFileName = new unsigned char[mFileNameLength+1]; - if (mFileName == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mFileName[mFileNameLength] = '\0'; - } - - /* grab extra field */ - if (mExtraFieldLength != 0) { - mExtraField = new unsigned char[mExtraFieldLength+1]; - if (mExtraField == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mExtraField[mExtraFieldLength] = '\0'; - } - -bail: - return result; -} - -/* - * Write a local file header. - */ -status_t ZipEntry::LocalFileHeader::write(FILE* fp) -{ - unsigned char buf[kLFHLen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mVersionToExtract); - ZipEntry::putShortLE(&buf[0x06], mGPBitFlag); - ZipEntry::putShortLE(&buf[0x08], mCompressionMethod); - ZipEntry::putShortLE(&buf[0x0a], mLastModFileTime); - ZipEntry::putShortLE(&buf[0x0c], mLastModFileDate); - ZipEntry::putLongLE(&buf[0x0e], mCRC32); - ZipEntry::putLongLE(&buf[0x12], mCompressedSize); - ZipEntry::putLongLE(&buf[0x16], mUncompressedSize); - ZipEntry::putShortLE(&buf[0x1a], mFileNameLength); - ZipEntry::putShortLE(&buf[0x1c], mExtraFieldLength); - - if (fwrite(buf, 1, kLFHLen, fp) != kLFHLen) - return UNKNOWN_ERROR; - - /* write filename */ - if (mFileNameLength != 0) { - if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength) - return UNKNOWN_ERROR; - } - - /* write "extra field" */ - if (mExtraFieldLength != 0) { - if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - - -/* - * Dump the contents of a LocalFileHeader object. - */ -void ZipEntry::LocalFileHeader::dump(void) const -{ - LOGD(" LocalFileHeader contents:\n"); - LOGD(" versToExt=%u gpBits=0x%04x compression=%u\n", - mVersionToExtract, mGPBitFlag, mCompressionMethod); - LOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", - mLastModFileTime, mLastModFileDate, mCRC32); - LOGD(" compressedSize=%lu uncompressedSize=%lu\n", - mCompressedSize, mUncompressedSize); - LOGD(" filenameLen=%u extraLen=%u\n", - mFileNameLength, mExtraFieldLength); - if (mFileName != NULL) - LOGD(" filename: '%s'\n", mFileName); -} - - -/* - * =========================================================================== - * ZipEntry::CentralDirEntry - * =========================================================================== - */ - -/* - * Read the central dir entry that appears next in the file. - * - * On entry, "fp" should be positioned on the signature bytes for the - * entry. On exit, "fp" will point at the signature word for the next - * entry or for the EOCD. - */ -status_t ZipEntry::CentralDirEntry::read(FILE* fp) -{ - status_t result = NO_ERROR; - unsigned char buf[kCDELen]; - - /* no re-use */ - assert(mFileName == NULL); - assert(mExtraField == NULL); - assert(mFileComment == NULL); - - if (fread(buf, 1, kCDELen, fp) != kCDELen) { - result = UNKNOWN_ERROR; - goto bail; - } - - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) { - LOGD("Whoops: didn't find expected signature\n"); - result = UNKNOWN_ERROR; - goto bail; - } - - mVersionMadeBy = ZipEntry::getShortLE(&buf[0x04]); - mVersionToExtract = ZipEntry::getShortLE(&buf[0x06]); - mGPBitFlag = ZipEntry::getShortLE(&buf[0x08]); - mCompressionMethod = ZipEntry::getShortLE(&buf[0x0a]); - mLastModFileTime = ZipEntry::getShortLE(&buf[0x0c]); - mLastModFileDate = ZipEntry::getShortLE(&buf[0x0e]); - mCRC32 = ZipEntry::getLongLE(&buf[0x10]); - mCompressedSize = ZipEntry::getLongLE(&buf[0x14]); - mUncompressedSize = ZipEntry::getLongLE(&buf[0x18]); - mFileNameLength = ZipEntry::getShortLE(&buf[0x1c]); - mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1e]); - mFileCommentLength = ZipEntry::getShortLE(&buf[0x20]); - mDiskNumberStart = ZipEntry::getShortLE(&buf[0x22]); - mInternalAttrs = ZipEntry::getShortLE(&buf[0x24]); - mExternalAttrs = ZipEntry::getLongLE(&buf[0x26]); - mLocalHeaderRelOffset = ZipEntry::getLongLE(&buf[0x2a]); - - // TODO: validate sizes and offsets - - /* grab filename */ - if (mFileNameLength != 0) { - mFileName = new unsigned char[mFileNameLength+1]; - if (mFileName == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mFileName[mFileNameLength] = '\0'; - } - - /* read "extra field" */ - if (mExtraFieldLength != 0) { - mExtraField = new unsigned char[mExtraFieldLength+1]; - if (mExtraField == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mExtraField[mExtraFieldLength] = '\0'; - } - - - /* grab comment, if any */ - if (mFileCommentLength != 0) { - mFileComment = new unsigned char[mFileCommentLength+1]; - if (mFileComment == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength) - { - result = UNKNOWN_ERROR; - goto bail; - } - mFileComment[mFileCommentLength] = '\0'; - } - -bail: - return result; -} - -/* - * Write a central dir entry. - */ -status_t ZipEntry::CentralDirEntry::write(FILE* fp) -{ - unsigned char buf[kCDELen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mVersionMadeBy); - ZipEntry::putShortLE(&buf[0x06], mVersionToExtract); - ZipEntry::putShortLE(&buf[0x08], mGPBitFlag); - ZipEntry::putShortLE(&buf[0x0a], mCompressionMethod); - ZipEntry::putShortLE(&buf[0x0c], mLastModFileTime); - ZipEntry::putShortLE(&buf[0x0e], mLastModFileDate); - ZipEntry::putLongLE(&buf[0x10], mCRC32); - ZipEntry::putLongLE(&buf[0x14], mCompressedSize); - ZipEntry::putLongLE(&buf[0x18], mUncompressedSize); - ZipEntry::putShortLE(&buf[0x1c], mFileNameLength); - ZipEntry::putShortLE(&buf[0x1e], mExtraFieldLength); - ZipEntry::putShortLE(&buf[0x20], mFileCommentLength); - ZipEntry::putShortLE(&buf[0x22], mDiskNumberStart); - ZipEntry::putShortLE(&buf[0x24], mInternalAttrs); - ZipEntry::putLongLE(&buf[0x26], mExternalAttrs); - ZipEntry::putLongLE(&buf[0x2a], mLocalHeaderRelOffset); - - if (fwrite(buf, 1, kCDELen, fp) != kCDELen) - return UNKNOWN_ERROR; - - /* write filename */ - if (mFileNameLength != 0) { - if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength) - return UNKNOWN_ERROR; - } - - /* write "extra field" */ - if (mExtraFieldLength != 0) { - if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) - return UNKNOWN_ERROR; - } - - /* write comment */ - if (mFileCommentLength != 0) { - if (fwrite(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - -/* - * Dump the contents of a CentralDirEntry object. - */ -void ZipEntry::CentralDirEntry::dump(void) const -{ - LOGD(" CentralDirEntry contents:\n"); - LOGD(" versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n", - mVersionMadeBy, mVersionToExtract, mGPBitFlag, mCompressionMethod); - LOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", - mLastModFileTime, mLastModFileDate, mCRC32); - LOGD(" compressedSize=%lu uncompressedSize=%lu\n", - mCompressedSize, mUncompressedSize); - LOGD(" filenameLen=%u extraLen=%u commentLen=%u\n", - mFileNameLength, mExtraFieldLength, mFileCommentLength); - LOGD(" diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n", - mDiskNumberStart, mInternalAttrs, mExternalAttrs, - mLocalHeaderRelOffset); - - if (mFileName != NULL) - LOGD(" filename: '%s'\n", mFileName); - if (mFileComment != NULL) - LOGD(" comment: '%s'\n", mFileComment); -} - diff --git a/libs/utils/ZipFile.cpp b/libs/utils/ZipFile.cpp deleted file mode 100644 index 89aa874..0000000 --- a/libs/utils/ZipFile.cpp +++ /dev/null @@ -1,1296 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Access to Zip archives. -// - -#define LOG_TAG "zip" - -#include "utils/ZipFile.h" -#include "utils/ZipUtils.h" -#include "utils/Log.h" - -#include <zlib.h> -#define DEF_MEM_LEVEL 8 // normally in zutil.h? - -#include <memory.h> -#include <sys/stat.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - -/* - * Some environments require the "b", some choke on it. - */ -#define FILE_OPEN_RO "rb" -#define FILE_OPEN_RW "r+b" -#define FILE_OPEN_RW_CREATE "w+b" - -/* should live somewhere else? */ -static status_t errnoToStatus(int err) -{ - if (err == ENOENT) - return NAME_NOT_FOUND; - else if (err == EACCES) - return PERMISSION_DENIED; - else - return UNKNOWN_ERROR; -} - -/* - * Open a file and parse its guts. - */ -status_t ZipFile::open(const char* zipFileName, int flags) -{ - bool newArchive = false; - - assert(mZipFp == NULL); // no reopen - - if ((flags & kOpenTruncate)) - flags |= kOpenCreate; // trunc implies create - - if ((flags & kOpenReadOnly) && (flags & kOpenReadWrite)) - return INVALID_OPERATION; // not both - if (!((flags & kOpenReadOnly) || (flags & kOpenReadWrite))) - return INVALID_OPERATION; // not neither - if ((flags & kOpenCreate) && !(flags & kOpenReadWrite)) - return INVALID_OPERATION; // create requires write - - if (flags & kOpenTruncate) { - newArchive = true; - } else { - newArchive = (access(zipFileName, F_OK) != 0); - if (!(flags & kOpenCreate) && newArchive) { - /* not creating, must already exist */ - LOGD("File %s does not exist", zipFileName); - return NAME_NOT_FOUND; - } - } - - /* open the file */ - const char* openflags; - if (flags & kOpenReadWrite) { - if (newArchive) - openflags = FILE_OPEN_RW_CREATE; - else - openflags = FILE_OPEN_RW; - } else { - openflags = FILE_OPEN_RO; - } - mZipFp = fopen(zipFileName, openflags); - if (mZipFp == NULL) { - int err = errno; - LOGD("fopen failed: %d\n", err); - return errnoToStatus(err); - } - - status_t result; - if (!newArchive) { - /* - * Load the central directory. If that fails, then this probably - * isn't a Zip archive. - */ - result = readCentralDir(); - } else { - /* - * Newly-created. The EndOfCentralDir constructor actually - * sets everything to be the way we want it (all zeroes). We - * set mNeedCDRewrite so that we create *something* if the - * caller doesn't add any files. (We could also just unlink - * the file if it's brand new and nothing was added, but that's - * probably doing more than we really should -- the user might - * have a need for empty zip files.) - */ - mNeedCDRewrite = true; - result = NO_ERROR; - } - - if (flags & kOpenReadOnly) - mReadOnly = true; - else - assert(!mReadOnly); - - return result; -} - -/* - * Return the Nth entry in the archive. - */ -ZipEntry* ZipFile::getEntryByIndex(int idx) const -{ - if (idx < 0 || idx >= (int) mEntries.size()) - return NULL; - - return mEntries[idx]; -} - -/* - * Find an entry by name. - */ -ZipEntry* ZipFile::getEntryByName(const char* fileName) const -{ - /* - * Do a stupid linear string-compare search. - * - * There are various ways to speed this up, especially since it's rare - * to intermingle changes to the archive with "get by name" calls. We - * don't want to sort the mEntries vector itself, however, because - * it's used to recreate the Central Directory. - * - * (Hash table works, parallel list of pointers in sorted order is good.) - */ - int idx; - - for (idx = mEntries.size()-1; idx >= 0; idx--) { - ZipEntry* pEntry = mEntries[idx]; - if (!pEntry->getDeleted() && - strcmp(fileName, pEntry->getFileName()) == 0) - { - return pEntry; - } - } - - return NULL; -} - -/* - * Empty the mEntries vector. - */ -void ZipFile::discardEntries(void) -{ - int count = mEntries.size(); - - while (--count >= 0) - delete mEntries[count]; - - mEntries.clear(); -} - - -/* - * Find the central directory and read the contents. - * - * The fun thing about ZIP archives is that they may or may not be - * readable from start to end. In some cases, notably for archives - * that were written to stdout, the only length information is in the - * central directory at the end of the file. - * - * Of course, the central directory can be followed by a variable-length - * comment field, so we have to scan through it backwards. The comment - * is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff - * itself, plus apparently sometimes people throw random junk on the end - * just for the fun of it. - * - * This is all a little wobbly. If the wrong value ends up in the EOCD - * area, we're hosed. This appears to be the way that everbody handles - * it though, so we're in pretty good company if this fails. - */ -status_t ZipFile::readCentralDir(void) -{ - status_t result = NO_ERROR; - unsigned char* buf = NULL; - off_t fileLength, seekStart; - long readAmount; - int i; - - fseek(mZipFp, 0, SEEK_END); - fileLength = ftell(mZipFp); - rewind(mZipFp); - - /* too small to be a ZIP archive? */ - if (fileLength < EndOfCentralDir::kEOCDLen) { - LOGD("Length is %ld -- too small\n", (long)fileLength); - result = INVALID_OPERATION; - goto bail; - } - - buf = new unsigned char[EndOfCentralDir::kMaxEOCDSearch]; - if (buf == NULL) { - LOGD("Failure allocating %d bytes for EOCD search", - EndOfCentralDir::kMaxEOCDSearch); - result = NO_MEMORY; - goto bail; - } - - if (fileLength > EndOfCentralDir::kMaxEOCDSearch) { - seekStart = fileLength - EndOfCentralDir::kMaxEOCDSearch; - readAmount = EndOfCentralDir::kMaxEOCDSearch; - } else { - seekStart = 0; - readAmount = (long) fileLength; - } - if (fseek(mZipFp, seekStart, SEEK_SET) != 0) { - LOGD("Failure seeking to end of zip at %ld", (long) seekStart); - result = UNKNOWN_ERROR; - goto bail; - } - - /* read the last part of the file into the buffer */ - if (fread(buf, 1, readAmount, mZipFp) != (size_t) readAmount) { - LOGD("short file? wanted %ld\n", readAmount); - result = UNKNOWN_ERROR; - goto bail; - } - - /* find the end-of-central-dir magic */ - for (i = readAmount - 4; i >= 0; i--) { - if (buf[i] == 0x50 && - ZipEntry::getLongLE(&buf[i]) == EndOfCentralDir::kSignature) - { - LOGV("+++ Found EOCD at buf+%d\n", i); - break; - } - } - if (i < 0) { - LOGD("EOCD not found, not Zip\n"); - result = INVALID_OPERATION; - goto bail; - } - - /* extract eocd values */ - result = mEOCD.readBuf(buf + i, readAmount - i); - if (result != NO_ERROR) { - LOGD("Failure reading %ld bytes of EOCD values", readAmount - i); - goto bail; - } - //mEOCD.dump(); - - if (mEOCD.mDiskNumber != 0 || mEOCD.mDiskWithCentralDir != 0 || - mEOCD.mNumEntries != mEOCD.mTotalNumEntries) - { - LOGD("Archive spanning not supported\n"); - result = INVALID_OPERATION; - goto bail; - } - - /* - * So far so good. "mCentralDirSize" is the size in bytes of the - * central directory, so we can just seek back that far to find it. - * We can also seek forward mCentralDirOffset bytes from the - * start of the file. - * - * We're not guaranteed to have the rest of the central dir in the - * buffer, nor are we guaranteed that the central dir will have any - * sort of convenient size. We need to skip to the start of it and - * read the header, then the other goodies. - * - * The only thing we really need right now is the file comment, which - * we're hoping to preserve. - */ - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - LOGD("Failure seeking to central dir offset %ld\n", - mEOCD.mCentralDirOffset); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * Loop through and read the central dir entries. - */ - LOGV("Scanning %d entries...\n", mEOCD.mTotalNumEntries); - int entry; - for (entry = 0; entry < mEOCD.mTotalNumEntries; entry++) { - ZipEntry* pEntry = new ZipEntry; - - result = pEntry->initFromCDE(mZipFp); - if (result != NO_ERROR) { - LOGD("initFromCDE failed\n"); - delete pEntry; - goto bail; - } - - mEntries.add(pEntry); - } - - - /* - * If all went well, we should now be back at the EOCD. - */ - { - unsigned char checkBuf[4]; - if (fread(checkBuf, 1, 4, mZipFp) != 4) { - LOGD("EOCD check read failed\n"); - result = INVALID_OPERATION; - goto bail; - } - if (ZipEntry::getLongLE(checkBuf) != EndOfCentralDir::kSignature) { - LOGD("EOCD read check failed\n"); - result = UNKNOWN_ERROR; - goto bail; - } - LOGV("+++ EOCD read check passed\n"); - } - -bail: - delete[] buf; - return result; -} - - -/* - * Add a new file to the archive. - * - * This requires creating and populating a ZipEntry structure, and copying - * the data into the file at the appropriate position. The "appropriate - * position" is the current location of the central directory, which we - * casually overwrite (we can put it back later). - * - * If we were concerned about safety, we would want to make all changes - * in a temp file and then overwrite the original after everything was - * safely written. Not really a concern for us. - */ -status_t ZipFile::addCommon(const char* fileName, const void* data, size_t size, - const char* storageName, int sourceType, int compressionMethod, - ZipEntry** ppEntry) -{ - ZipEntry* pEntry = NULL; - status_t result = NO_ERROR; - long lfhPosn, startPosn, endPosn, uncompressedLen; - FILE* inputFp = NULL; - unsigned long crc; - time_t modWhen; - - if (mReadOnly) - return INVALID_OPERATION; - - assert(compressionMethod == ZipEntry::kCompressDeflated || - compressionMethod == ZipEntry::kCompressStored); - - /* make sure we're in a reasonable state */ - assert(mZipFp != NULL); - assert(mEntries.size() == mEOCD.mTotalNumEntries); - - /* make sure it doesn't already exist */ - if (getEntryByName(storageName) != NULL) - return ALREADY_EXISTS; - - if (!data) { - inputFp = fopen(fileName, FILE_OPEN_RO); - if (inputFp == NULL) - return errnoToStatus(errno); - } - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - - pEntry = new ZipEntry; - pEntry->initNew(storageName, NULL); - - /* - * From here on out, failures are more interesting. - */ - mNeedCDRewrite = true; - - /* - * Write the LFH, even though it's still mostly blank. We need it - * as a place-holder. In theory the LFH isn't necessary, but in - * practice some utilities demand it. - */ - lfhPosn = ftell(mZipFp); - pEntry->mLFH.write(mZipFp); - startPosn = ftell(mZipFp); - - /* - * Copy the data in, possibly compressing it as we go. - */ - if (sourceType == ZipEntry::kCompressStored) { - if (compressionMethod == ZipEntry::kCompressDeflated) { - bool failed = false; - result = compressFpToFp(mZipFp, inputFp, data, size, &crc); - if (result != NO_ERROR) { - LOGD("compression failed, storing\n"); - failed = true; - } else { - /* - * Make sure it has compressed "enough". This probably ought - * to be set through an API call, but I don't expect our - * criteria to change over time. - */ - long src = inputFp ? ftell(inputFp) : size; - long dst = ftell(mZipFp) - startPosn; - if (dst + (dst / 10) > src) { - LOGD("insufficient compression (src=%ld dst=%ld), storing\n", - src, dst); - failed = true; - } - } - - if (failed) { - compressionMethod = ZipEntry::kCompressStored; - if (inputFp) rewind(inputFp); - fseek(mZipFp, startPosn, SEEK_SET); - /* fall through to kCompressStored case */ - } - } - /* handle "no compression" request, or failed compression from above */ - if (compressionMethod == ZipEntry::kCompressStored) { - if (inputFp) { - result = copyFpToFp(mZipFp, inputFp, &crc); - } else { - result = copyDataToFp(mZipFp, data, size, &crc); - } - if (result != NO_ERROR) { - // don't need to truncate; happens in CDE rewrite - LOGD("failed copying data in\n"); - goto bail; - } - } - - // currently seeked to end of file - uncompressedLen = inputFp ? ftell(inputFp) : size; - } else if (sourceType == ZipEntry::kCompressDeflated) { - /* we should support uncompressed-from-compressed, but it's not - * important right now */ - assert(compressionMethod == ZipEntry::kCompressDeflated); - - bool scanResult; - int method; - long compressedLen; - - scanResult = ZipUtils::examineGzip(inputFp, &method, &uncompressedLen, - &compressedLen, &crc); - if (!scanResult || method != ZipEntry::kCompressDeflated) { - LOGD("this isn't a deflated gzip file?"); - result = UNKNOWN_ERROR; - goto bail; - } - - result = copyPartialFpToFp(mZipFp, inputFp, compressedLen, NULL); - if (result != NO_ERROR) { - LOGD("failed copying gzip data in\n"); - goto bail; - } - } else { - assert(false); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * We could write the "Data Descriptor", but there doesn't seem to - * be any point since we're going to go back and write the LFH. - * - * Update file offsets. - */ - endPosn = ftell(mZipFp); // seeked to end of compressed data - - /* - * Success! Fill out new values. - */ - pEntry->setDataInfo(uncompressedLen, endPosn - startPosn, crc, - compressionMethod); - modWhen = getModTime(inputFp ? fileno(inputFp) : fileno(mZipFp)); - pEntry->setModWhen(modWhen); - pEntry->setLFHOffset(lfhPosn); - mEOCD.mNumEntries++; - mEOCD.mTotalNumEntries++; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - mEOCD.mCentralDirOffset = endPosn; - - /* - * Go back and write the LFH. - */ - if (fseek(mZipFp, lfhPosn, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - pEntry->mLFH.write(mZipFp); - - /* - * Add pEntry to the list. - */ - mEntries.add(pEntry); - if (ppEntry != NULL) - *ppEntry = pEntry; - pEntry = NULL; - -bail: - if (inputFp != NULL) - fclose(inputFp); - delete pEntry; - return result; -} - -/* - * Add an entry by copying it from another zip file. If "padding" is - * nonzero, the specified number of bytes will be added to the "extra" - * field in the header. - * - * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. - */ -status_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry, - int padding, ZipEntry** ppEntry) -{ - ZipEntry* pEntry = NULL; - status_t result; - long lfhPosn, endPosn; - - if (mReadOnly) - return INVALID_OPERATION; - - /* make sure we're in a reasonable state */ - assert(mZipFp != NULL); - assert(mEntries.size() == mEOCD.mTotalNumEntries); - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - - pEntry = new ZipEntry; - if (pEntry == NULL) { - result = NO_MEMORY; - goto bail; - } - - result = pEntry->initFromExternal(pSourceZip, pSourceEntry); - if (result != NO_ERROR) - goto bail; - if (padding != 0) { - result = pEntry->addPadding(padding); - if (result != NO_ERROR) - goto bail; - } - - /* - * From here on out, failures are more interesting. - */ - mNeedCDRewrite = true; - - /* - * Write the LFH. Since we're not recompressing the data, we already - * have all of the fields filled out. - */ - lfhPosn = ftell(mZipFp); - pEntry->mLFH.write(mZipFp); - - /* - * Copy the data over. - * - * If the "has data descriptor" flag is set, we want to copy the DD - * fields as well. This is a fixed-size area immediately following - * the data. - */ - if (fseek(pSourceZip->mZipFp, pSourceEntry->getFileOffset(), SEEK_SET) != 0) - { - result = UNKNOWN_ERROR; - goto bail; - } - - off_t copyLen; - copyLen = pSourceEntry->getCompressedLen(); - if ((pSourceEntry->mLFH.mGPBitFlag & ZipEntry::kUsesDataDescr) != 0) - copyLen += ZipEntry::kDataDescriptorLen; - - if (copyPartialFpToFp(mZipFp, pSourceZip->mZipFp, copyLen, NULL) - != NO_ERROR) - { - LOGW("copy of '%s' failed\n", pEntry->mCDE.mFileName); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * Update file offsets. - */ - endPosn = ftell(mZipFp); - - /* - * Success! Fill out new values. - */ - pEntry->setLFHOffset(lfhPosn); // sets mCDE.mLocalHeaderRelOffset - mEOCD.mNumEntries++; - mEOCD.mTotalNumEntries++; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - mEOCD.mCentralDirOffset = endPosn; - - /* - * Add pEntry to the list. - */ - mEntries.add(pEntry); - if (ppEntry != NULL) - *ppEntry = pEntry; - pEntry = NULL; - - result = NO_ERROR; - -bail: - delete pEntry; - return result; -} - -/* - * Copy all of the bytes in "src" to "dst". - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the data. - */ -status_t ZipFile::copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32) -{ - unsigned char tmpBuf[32768]; - size_t count; - - *pCRC32 = crc32(0L, Z_NULL, 0); - - while (1) { - count = fread(tmpBuf, 1, sizeof(tmpBuf), srcFp); - if (ferror(srcFp) || ferror(dstFp)) - return errnoToStatus(errno); - if (count == 0) - break; - - *pCRC32 = crc32(*pCRC32, tmpBuf, count); - - if (fwrite(tmpBuf, 1, count, dstFp) != count) { - LOGD("fwrite %d bytes failed\n", (int) count); - return UNKNOWN_ERROR; - } - } - - return NO_ERROR; -} - -/* - * Copy all of the bytes in "src" to "dst". - * - * On exit, "dstFp" will be seeked immediately past the data. - */ -status_t ZipFile::copyDataToFp(FILE* dstFp, - const void* data, size_t size, unsigned long* pCRC32) -{ - size_t count; - - *pCRC32 = crc32(0L, Z_NULL, 0); - if (size > 0) { - *pCRC32 = crc32(*pCRC32, (const unsigned char*)data, size); - if (fwrite(data, 1, size, dstFp) != size) { - LOGD("fwrite %d bytes failed\n", (int) size); - return UNKNOWN_ERROR; - } - } - - return NO_ERROR; -} - -/* - * Copy some of the bytes in "src" to "dst". - * - * If "pCRC32" is NULL, the CRC will not be computed. - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the data just written. - */ -status_t ZipFile::copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length, - unsigned long* pCRC32) -{ - unsigned char tmpBuf[32768]; - size_t count; - - if (pCRC32 != NULL) - *pCRC32 = crc32(0L, Z_NULL, 0); - - while (length) { - long readSize; - - readSize = sizeof(tmpBuf); - if (readSize > length) - readSize = length; - - count = fread(tmpBuf, 1, readSize, srcFp); - if ((long) count != readSize) { // error or unexpected EOF - LOGD("fread %d bytes failed\n", (int) readSize); - return UNKNOWN_ERROR; - } - - if (pCRC32 != NULL) - *pCRC32 = crc32(*pCRC32, tmpBuf, count); - - if (fwrite(tmpBuf, 1, count, dstFp) != count) { - LOGD("fwrite %d bytes failed\n", (int) count); - return UNKNOWN_ERROR; - } - - length -= readSize; - } - - return NO_ERROR; -} - -/* - * Compress all of the data in "srcFp" and write it to "dstFp". - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the compressed data. - */ -status_t ZipFile::compressFpToFp(FILE* dstFp, FILE* srcFp, - const void* data, size_t size, unsigned long* pCRC32) -{ - status_t result = NO_ERROR; - const size_t kBufSize = 32768; - unsigned char* inBuf = NULL; - unsigned char* outBuf = NULL; - z_stream zstream; - bool atEof = false; // no feof() aviailable yet - unsigned long crc; - int zerr; - - /* - * Create an input buffer and an output buffer. - */ - inBuf = new unsigned char[kBufSize]; - outBuf = new unsigned char[kBufSize]; - if (inBuf == NULL || outBuf == NULL) { - result = NO_MEMORY; - goto bail; - } - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - zstream.data_type = Z_UNKNOWN; - - zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); - if (zerr != Z_OK) { - result = UNKNOWN_ERROR; - if (zerr == Z_VERSION_ERROR) { - LOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - LOGD("Call to deflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - crc = crc32(0L, Z_NULL, 0); - - /* - * Loop while we have data. - */ - do { - size_t getSize; - int flush; - - /* only read if the input buffer is empty */ - if (zstream.avail_in == 0 && !atEof) { - LOGV("+++ reading %d bytes\n", (int)kBufSize); - if (data) { - getSize = size > kBufSize ? kBufSize : size; - memcpy(inBuf, data, getSize); - data = ((const char*)data) + getSize; - size -= getSize; - } else { - getSize = fread(inBuf, 1, kBufSize, srcFp); - if (ferror(srcFp)) { - LOGD("deflate read failed (errno=%d)\n", errno); - goto z_bail; - } - } - if (getSize < kBufSize) { - LOGV("+++ got %d bytes, EOF reached\n", - (int)getSize); - atEof = true; - } - - crc = crc32(crc, inBuf, getSize); - - zstream.next_in = inBuf; - zstream.avail_in = getSize; - } - - if (atEof) - flush = Z_FINISH; /* tell zlib that we're done */ - else - flush = Z_NO_FLUSH; /* more to come! */ - - zerr = deflate(&zstream, flush); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - LOGD("zlib deflate call failed (zerr=%d)\n", zerr); - result = UNKNOWN_ERROR; - goto z_bail; - } - - /* write when we're full or when we're done */ - if (zstream.avail_out == 0 || - (zerr == Z_STREAM_END && zstream.avail_out != (uInt) kBufSize)) - { - LOGV("+++ writing %d bytes\n", (int) (zstream.next_out - outBuf)); - if (fwrite(outBuf, 1, zstream.next_out - outBuf, dstFp) != - (size_t)(zstream.next_out - outBuf)) - { - LOGD("write %d failed in deflate\n", - (int) (zstream.next_out - outBuf)); - goto z_bail; - } - - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - } - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - *pCRC32 = crc; - -z_bail: - deflateEnd(&zstream); /* free up any allocated structures */ - -bail: - delete[] inBuf; - delete[] outBuf; - - return result; -} - -/* - * Mark an entry as deleted. - * - * We will eventually need to crunch the file down, but if several files - * are being removed (perhaps as part of an "update" process) we can make - * things considerably faster by deferring the removal to "flush" time. - */ -status_t ZipFile::remove(ZipEntry* pEntry) -{ - /* - * Should verify that pEntry is actually part of this archive, and - * not some stray ZipEntry from a different file. - */ - - /* mark entry as deleted, and mark archive as dirty */ - pEntry->setDeleted(); - mNeedCDRewrite = true; - return NO_ERROR; -} - -/* - * Flush any pending writes. - * - * In particular, this will crunch out deleted entries, and write the - * Central Directory and EOCD if we have stomped on them. - */ -status_t ZipFile::flush(void) -{ - status_t result = NO_ERROR; - long eocdPosn; - int i, count; - - if (mReadOnly) - return INVALID_OPERATION; - if (!mNeedCDRewrite) - return NO_ERROR; - - assert(mZipFp != NULL); - - result = crunchArchive(); - if (result != NO_ERROR) - return result; - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) - return UNKNOWN_ERROR; - - count = mEntries.size(); - for (i = 0; i < count; i++) { - ZipEntry* pEntry = mEntries[i]; - pEntry->mCDE.write(mZipFp); - } - - eocdPosn = ftell(mZipFp); - mEOCD.mCentralDirSize = eocdPosn - mEOCD.mCentralDirOffset; - - mEOCD.write(mZipFp); - - /* - * If we had some stuff bloat up during compression and get replaced - * with plain files, or if we deleted some entries, there's a lot - * of wasted space at the end of the file. Remove it now. - */ - if (ftruncate(fileno(mZipFp), ftell(mZipFp)) != 0) { - LOGW("ftruncate failed %ld: %s\n", ftell(mZipFp), strerror(errno)); - // not fatal - } - - /* should we clear the "newly added" flag in all entries now? */ - - mNeedCDRewrite = false; - return NO_ERROR; -} - -/* - * Crunch deleted files out of an archive by shifting the later files down. - * - * Because we're not using a temp file, we do the operation inside the - * current file. - */ -status_t ZipFile::crunchArchive(void) -{ - status_t result = NO_ERROR; - int i, count; - long delCount, adjust; - -#if 0 - printf("CONTENTS:\n"); - for (i = 0; i < (int) mEntries.size(); i++) { - printf(" %d: lfhOff=%ld del=%d\n", - i, mEntries[i]->getLFHOffset(), mEntries[i]->getDeleted()); - } - printf(" END is %ld\n", (long) mEOCD.mCentralDirOffset); -#endif - - /* - * Roll through the set of files, shifting them as appropriate. We - * could probably get a slight performance improvement by sliding - * multiple files down at once (because we could use larger reads - * when operating on batches of small files), but it's not that useful. - */ - count = mEntries.size(); - delCount = adjust = 0; - for (i = 0; i < count; i++) { - ZipEntry* pEntry = mEntries[i]; - long span; - - if (pEntry->getLFHOffset() != 0) { - long nextOffset; - - /* Get the length of this entry by finding the offset - * of the next entry. Directory entries don't have - * file offsets, so we need to find the next non-directory - * entry. - */ - nextOffset = 0; - for (int ii = i+1; nextOffset == 0 && ii < count; ii++) - nextOffset = mEntries[ii]->getLFHOffset(); - if (nextOffset == 0) - nextOffset = mEOCD.mCentralDirOffset; - span = nextOffset - pEntry->getLFHOffset(); - - assert(span >= ZipEntry::LocalFileHeader::kLFHLen); - } else { - /* This is a directory entry. It doesn't have - * any actual file contents, so there's no need to - * move anything. - */ - span = 0; - } - - //printf("+++ %d: off=%ld span=%ld del=%d [count=%d]\n", - // i, pEntry->getLFHOffset(), span, pEntry->getDeleted(), count); - - if (pEntry->getDeleted()) { - adjust += span; - delCount++; - - delete pEntry; - mEntries.removeAt(i); - - /* adjust loop control */ - count--; - i--; - } else if (span != 0 && adjust > 0) { - /* shuffle this entry back */ - //printf("+++ Shuffling '%s' back %ld\n", - // pEntry->getFileName(), adjust); - result = filemove(mZipFp, pEntry->getLFHOffset() - adjust, - pEntry->getLFHOffset(), span); - if (result != NO_ERROR) { - /* this is why you use a temp file */ - LOGE("error during crunch - archive is toast\n"); - return result; - } - - pEntry->setLFHOffset(pEntry->getLFHOffset() - adjust); - } - } - - /* - * Fix EOCD info. We have to wait until the end to do some of this - * because we use mCentralDirOffset to determine "span" for the - * last entry. - */ - mEOCD.mCentralDirOffset -= adjust; - mEOCD.mNumEntries -= delCount; - mEOCD.mTotalNumEntries -= delCount; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - - assert(mEOCD.mNumEntries == mEOCD.mTotalNumEntries); - assert(mEOCD.mNumEntries == count); - - return result; -} - -/* - * Works like memmove(), but on pieces of a file. - */ -status_t ZipFile::filemove(FILE* fp, off_t dst, off_t src, size_t n) -{ - if (dst == src || n <= 0) - return NO_ERROR; - - unsigned char readBuf[32768]; - - if (dst < src) { - /* shift stuff toward start of file; must read from start */ - while (n != 0) { - size_t getSize = sizeof(readBuf); - if (getSize > n) - getSize = n; - - if (fseek(fp, (long) src, SEEK_SET) != 0) { - LOGD("filemove src seek %ld failed\n", (long) src); - return UNKNOWN_ERROR; - } - - if (fread(readBuf, 1, getSize, fp) != getSize) { - LOGD("filemove read %ld off=%ld failed\n", - (long) getSize, (long) src); - return UNKNOWN_ERROR; - } - - if (fseek(fp, (long) dst, SEEK_SET) != 0) { - LOGD("filemove dst seek %ld failed\n", (long) dst); - return UNKNOWN_ERROR; - } - - if (fwrite(readBuf, 1, getSize, fp) != getSize) { - LOGD("filemove write %ld off=%ld failed\n", - (long) getSize, (long) dst); - return UNKNOWN_ERROR; - } - - src += getSize; - dst += getSize; - n -= getSize; - } - } else { - /* shift stuff toward end of file; must read from end */ - assert(false); // write this someday, maybe - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - - -/* - * Get the modification time from a file descriptor. - */ -time_t ZipFile::getModTime(int fd) -{ - struct stat sb; - - if (fstat(fd, &sb) < 0) { - LOGD("HEY: fstat on fd %d failed\n", fd); - return (time_t) -1; - } - - return sb.st_mtime; -} - - -#if 0 /* this is a bad idea */ -/* - * Get a copy of the Zip file descriptor. - * - * We don't allow this if the file was opened read-write because we tend - * to leave the file contents in an uncertain state between calls to - * flush(). The duplicated file descriptor should only be valid for reads. - */ -int ZipFile::getZipFd(void) const -{ - if (!mReadOnly) - return INVALID_OPERATION; - assert(mZipFp != NULL); - - int fd; - fd = dup(fileno(mZipFp)); - if (fd < 0) { - LOGD("didn't work, errno=%d\n", errno); - } - - return fd; -} -#endif - - -#if 0 -/* - * Expand data. - */ -bool ZipFile::uncompress(const ZipEntry* pEntry, void* buf) const -{ - return false; -} -#endif - -// free the memory when you're done -void* ZipFile::uncompress(const ZipEntry* entry) -{ - size_t unlen = entry->getUncompressedLen(); - size_t clen = entry->getCompressedLen(); - - void* buf = malloc(unlen); - if (buf == NULL) { - return NULL; - } - - fseek(mZipFp, 0, SEEK_SET); - - off_t offset = entry->getFileOffset(); - if (fseek(mZipFp, offset, SEEK_SET) != 0) { - goto bail; - } - - switch (entry->getCompressionMethod()) - { - case ZipEntry::kCompressStored: { - ssize_t amt = fread(buf, 1, unlen, mZipFp); - if (amt != (ssize_t)unlen) { - goto bail; - } -#if 0 - printf("data...\n"); - const unsigned char* p = (unsigned char*)buf; - const unsigned char* end = p+unlen; - for (int i=0; i<32 && p < end; i++) { - printf("0x%08x ", (int)(offset+(i*0x10))); - for (int j=0; j<0x10 && p < end; j++) { - printf(" %02x", *p); - p++; - } - printf("\n"); - } -#endif - - } - break; - case ZipEntry::kCompressDeflated: { - if (!ZipUtils::inflateToBuffer(mZipFp, buf, unlen, clen)) { - goto bail; - } - } - break; - default: - goto bail; - } - return buf; - -bail: - free(buf); - return NULL; -} - - -/* - * =========================================================================== - * ZipFile::EndOfCentralDir - * =========================================================================== - */ - -/* - * Read the end-of-central-dir fields. - * - * "buf" should be positioned at the EOCD signature, and should contain - * the entire EOCD area including the comment. - */ -status_t ZipFile::EndOfCentralDir::readBuf(const unsigned char* buf, int len) -{ - /* don't allow re-use */ - assert(mComment == NULL); - - if (len < kEOCDLen) { - /* looks like ZIP file got truncated */ - LOGD(" Zip EOCD: expected >= %d bytes, found %d\n", - kEOCDLen, len); - return INVALID_OPERATION; - } - - /* this should probably be an assert() */ - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) - return UNKNOWN_ERROR; - - mDiskNumber = ZipEntry::getShortLE(&buf[0x04]); - mDiskWithCentralDir = ZipEntry::getShortLE(&buf[0x06]); - mNumEntries = ZipEntry::getShortLE(&buf[0x08]); - mTotalNumEntries = ZipEntry::getShortLE(&buf[0x0a]); - mCentralDirSize = ZipEntry::getLongLE(&buf[0x0c]); - mCentralDirOffset = ZipEntry::getLongLE(&buf[0x10]); - mCommentLen = ZipEntry::getShortLE(&buf[0x14]); - - // TODO: validate mCentralDirOffset - - if (mCommentLen > 0) { - if (kEOCDLen + mCommentLen > len) { - LOGD("EOCD(%d) + comment(%d) exceeds len (%d)\n", - kEOCDLen, mCommentLen, len); - return UNKNOWN_ERROR; - } - mComment = new unsigned char[mCommentLen]; - memcpy(mComment, buf + kEOCDLen, mCommentLen); - } - - return NO_ERROR; -} - -/* - * Write an end-of-central-directory section. - */ -status_t ZipFile::EndOfCentralDir::write(FILE* fp) -{ - unsigned char buf[kEOCDLen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mDiskNumber); - ZipEntry::putShortLE(&buf[0x06], mDiskWithCentralDir); - ZipEntry::putShortLE(&buf[0x08], mNumEntries); - ZipEntry::putShortLE(&buf[0x0a], mTotalNumEntries); - ZipEntry::putLongLE(&buf[0x0c], mCentralDirSize); - ZipEntry::putLongLE(&buf[0x10], mCentralDirOffset); - ZipEntry::putShortLE(&buf[0x14], mCommentLen); - - if (fwrite(buf, 1, kEOCDLen, fp) != kEOCDLen) - return UNKNOWN_ERROR; - if (mCommentLen > 0) { - assert(mComment != NULL); - if (fwrite(mComment, mCommentLen, 1, fp) != mCommentLen) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - -/* - * Dump the contents of an EndOfCentralDir object. - */ -void ZipFile::EndOfCentralDir::dump(void) const -{ - LOGD(" EndOfCentralDir contents:\n"); - LOGD(" diskNum=%u diskWCD=%u numEnt=%u totalNumEnt=%u\n", - mDiskNumber, mDiskWithCentralDir, mNumEntries, mTotalNumEntries); - LOGD(" centDirSize=%lu centDirOff=%lu commentLen=%u\n", - mCentralDirSize, mCentralDirOffset, mCommentLen); -} - diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp deleted file mode 100644 index d312daf..0000000 --- a/libs/utils/ZipFileCRO.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "utils/ZipFileCRO.h" -#include "utils/ZipFileRO.h" - -using namespace android; - -ZipFileCRO ZipFileXRO_open(const char* path) { - ZipFileRO* zip = new ZipFileRO(); - if (zip->open(path) == NO_ERROR) { - return (ZipFileCRO)zip; - } - return NULL; -} - -void ZipFileCRO_destroy(ZipFileCRO zipToken) { - ZipFileRO* zip = (ZipFileRO*)zipToken; - delete zip; -} - -ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zipToken, - const char* fileName) { - ZipFileRO* zip = (ZipFileRO*)zipToken; - return (ZipEntryCRO)zip->findEntryByName(fileName); -} - -bool ZipFileCRO_getEntryInfo(ZipFileCRO zipToken, ZipEntryRO entryToken, - int* pMethod, long* pUncompLen, - long* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) { - ZipFileRO* zip = (ZipFileRO*)zipToken; - ZipEntryRO entry = (ZipEntryRO)entryToken; - return zip->getEntryInfo(entry, pMethod, pUncompLen, pCompLen, pOffset, - pModWhen, pCrc32); -} - -bool ZipFileCRO_uncompressEntry(ZipFileCRO zipToken, ZipEntryRO entryToken, int fd) { - ZipFileRO* zip = (ZipFileRO*)zipToken; - ZipEntryRO entry = (ZipEntryRO)entryToken; - return zip->uncompressEntry(entry, fd); -} diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp deleted file mode 100644 index ae8c719..0000000 --- a/libs/utils/ZipFileRO.cpp +++ /dev/null @@ -1,724 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Read-only access to Zip archives, with minimal heap allocation. -// -#define LOG_TAG "zipro" -//#define LOG_NDEBUG 0 -#include "utils/ZipFileRO.h" -#include "utils/Log.h" -#include "utils/misc.h" - -#include <zlib.h> - -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - -/* - * Zip file constants. - */ -#define kEOCDSignature 0x06054b50 -#define kEOCDLen 22 -#define kEOCDNumEntries 8 // offset to #of entries in file -#define kEOCDFileOffset 16 // offset to central directory - -#define kMaxCommentLen 65535 // longest possible in ushort -#define kMaxEOCDSearch (kMaxCommentLen + kEOCDLen) - -#define kLFHSignature 0x04034b50 -#define kLFHLen 30 // excluding variable-len fields -#define kLFHNameLen 26 // offset to filename length -#define kLFHExtraLen 28 // offset to extra length - -#define kCDESignature 0x02014b50 -#define kCDELen 46 // excluding variable-len fields -#define kCDEMethod 10 // offset to compression method -#define kCDEModWhen 12 // offset to modification timestamp -#define kCDECRC 16 // offset to entry CRC -#define kCDECompLen 20 // offset to compressed length -#define kCDEUncompLen 24 // offset to uncompressed length -#define kCDENameLen 28 // offset to filename length -#define kCDEExtraLen 30 // offset to extra length -#define kCDECommentLen 32 // offset to comment length -#define kCDELocalOffset 42 // offset to local hdr - -/* - * The values we return for ZipEntryRO use 0 as an invalid value, so we - * want to adjust the hash table index by a fixed amount. Using a large - * value helps insure that people don't mix & match arguments, e.g. to - * findEntryByIndex(). - */ -#define kZipEntryAdj 10000 - -/* - * Convert a ZipEntryRO to a hash table index, verifying that it's in a - * valid range. - */ -int ZipFileRO::entryToIndex(const ZipEntryRO entry) const -{ - long ent = ((long) entry) - kZipEntryAdj; - if (ent < 0 || ent >= mHashTableSize || mHashTable[ent].name == NULL) { - LOGW("Invalid ZipEntryRO %p (%ld)\n", entry, ent); - return -1; - } - return ent; -} - - -/* - * Open the specified file read-only. We memory-map the entire thing and - * close the file before returning. - */ -status_t ZipFileRO::open(const char* zipFileName) -{ - int fd = -1; - off_t length; - - assert(mFileMap == NULL); - - /* - * Open and map the specified file. - */ - fd = ::open(zipFileName, O_RDONLY); - if (fd < 0) { - LOGW("Unable to open zip '%s': %s\n", zipFileName, strerror(errno)); - return NAME_NOT_FOUND; - } - - length = lseek(fd, 0, SEEK_END); - if (length < 0) { - close(fd); - return UNKNOWN_ERROR; - } - - mFileMap = new FileMap(); - if (mFileMap == NULL) { - close(fd); - return NO_MEMORY; - } - if (!mFileMap->create(zipFileName, fd, 0, length, true)) { - LOGW("Unable to map '%s': %s\n", zipFileName, strerror(errno)); - close(fd); - return UNKNOWN_ERROR; - } - - mFd = fd; - - /* - * Got it mapped, verify it and create data structures for fast access. - */ - if (!parseZipArchive()) { - mFileMap->release(); - mFileMap = NULL; - return UNKNOWN_ERROR; - } - - return OK; -} - -/* - * Parse the Zip archive, verifying its contents and initializing internal - * data structures. - */ -bool ZipFileRO::parseZipArchive(void) -{ -#define CHECK_OFFSET(_off) { \ - if ((unsigned int) (_off) >= maxOffset) { \ - LOGE("ERROR: bad offset %u (max %d): %s\n", \ - (unsigned int) (_off), maxOffset, #_off); \ - goto bail; \ - } \ - } - const unsigned char* basePtr = (const unsigned char*)mFileMap->getDataPtr(); - const unsigned char* ptr; - size_t length = mFileMap->getDataLength(); - bool result = false; - unsigned int i, numEntries, cdOffset; - unsigned int val; - - /* - * The first 4 bytes of the file will either be the local header - * signature for the first file (kLFHSignature) or, if the archive doesn't - * have any files in it, the end-of-central-directory signature - * (kEOCDSignature). - */ - val = get4LE(basePtr); - if (val == kEOCDSignature) { - LOGI("Found Zip archive, but it looks empty\n"); - goto bail; - } else if (val != kLFHSignature) { - LOGV("Not a Zip archive (found 0x%08x)\n", val); - goto bail; - } - - /* - * Find the EOCD. We'll find it immediately unless they have a file - * comment. - */ - ptr = basePtr + length - kEOCDLen; - - while (ptr >= basePtr) { - if (*ptr == (kEOCDSignature & 0xff) && get4LE(ptr) == kEOCDSignature) - break; - ptr--; - } - if (ptr < basePtr) { - LOGI("Could not find end-of-central-directory in Zip\n"); - goto bail; - } - - /* - * There are two interesting items in the EOCD block: the number of - * entries in the file, and the file offset of the start of the - * central directory. - * - * (There's actually a count of the #of entries in this file, and for - * all files which comprise a spanned archive, but for our purposes - * we're only interested in the current file. Besides, we expect the - * two to be equivalent for our stuff.) - */ - numEntries = get2LE(ptr + kEOCDNumEntries); - cdOffset = get4LE(ptr + kEOCDFileOffset); - - /* valid offsets are [0,EOCD] */ - unsigned int maxOffset; - maxOffset = (ptr - basePtr) +1; - - LOGV("+++ numEntries=%d cdOffset=%d\n", numEntries, cdOffset); - if (numEntries == 0 || cdOffset >= length) { - LOGW("Invalid entries=%d offset=%d (len=%zd)\n", - numEntries, cdOffset, length); - goto bail; - } - - /* - * Create hash table. We have a minimum 75% load factor, possibly as - * low as 50% after we round off to a power of 2. - */ - mNumEntries = numEntries; - mHashTableSize = roundUpPower2(1 + ((numEntries * 4) / 3)); - mHashTable = (HashEntry*) calloc(1, sizeof(HashEntry) * mHashTableSize); - - /* - * Walk through the central directory, adding entries to the hash - * table. - */ - ptr = basePtr + cdOffset; - for (i = 0; i < numEntries; i++) { - unsigned int fileNameLen, extraLen, commentLen, localHdrOffset; - const unsigned char* localHdr; - unsigned int hash; - - if (get4LE(ptr) != kCDESignature) { - LOGW("Missed a central dir sig (at %d)\n", i); - goto bail; - } - if (ptr + kCDELen > basePtr + length) { - LOGW("Ran off the end (at %d)\n", i); - goto bail; - } - - localHdrOffset = get4LE(ptr + kCDELocalOffset); - CHECK_OFFSET(localHdrOffset); - fileNameLen = get2LE(ptr + kCDENameLen); - extraLen = get2LE(ptr + kCDEExtraLen); - commentLen = get2LE(ptr + kCDECommentLen); - - //LOGV("+++ %d: localHdr=%d fnl=%d el=%d cl=%d\n", - // i, localHdrOffset, fileNameLen, extraLen, commentLen); - //LOGV(" '%.*s'\n", fileNameLen, ptr + kCDELen); - - /* add the CDE filename to the hash table */ - hash = computeHash((const char*)ptr + kCDELen, fileNameLen); - addToHash((const char*)ptr + kCDELen, fileNameLen, hash); - - localHdr = basePtr + localHdrOffset; - if (get4LE(localHdr) != kLFHSignature) { - LOGW("Bad offset to local header: %d (at %d)\n", - localHdrOffset, i); - goto bail; - } - - ptr += kCDELen + fileNameLen + extraLen + commentLen; - CHECK_OFFSET(ptr - basePtr); - } - - result = true; - -bail: - return result; -#undef CHECK_OFFSET -} - - -/* - * Simple string hash function for non-null-terminated strings. - */ -/*static*/ unsigned int ZipFileRO::computeHash(const char* str, int len) -{ - unsigned int hash = 0; - - while (len--) - hash = hash * 31 + *str++; - - return hash; -} - -/* - * Add a new entry to the hash table. - */ -void ZipFileRO::addToHash(const char* str, int strLen, unsigned int hash) -{ - int ent = hash & (mHashTableSize-1); - - /* - * We over-allocate the table, so we're guaranteed to find an empty slot. - */ - while (mHashTable[ent].name != NULL) - ent = (ent + 1) & (mHashTableSize-1); - - mHashTable[ent].name = str; - mHashTable[ent].nameLen = strLen; -} - -/* - * Find a matching entry. - * - * Returns 0 if not found. - */ -ZipEntryRO ZipFileRO::findEntryByName(const char* fileName) const -{ - int nameLen = strlen(fileName); - unsigned int hash = computeHash(fileName, nameLen); - int ent = hash & (mHashTableSize-1); - - while (mHashTable[ent].name != NULL) { - if (mHashTable[ent].nameLen == nameLen && - memcmp(mHashTable[ent].name, fileName, nameLen) == 0) - { - /* match */ - return (ZipEntryRO) (ent + kZipEntryAdj); - } - - ent = (ent + 1) & (mHashTableSize-1); - } - - return NULL; -} - -/* - * Find the Nth entry. - * - * This currently involves walking through the sparse hash table, counting - * non-empty entries. If we need to speed this up we can either allocate - * a parallel lookup table or (perhaps better) provide an iterator interface. - */ -ZipEntryRO ZipFileRO::findEntryByIndex(int idx) const -{ - if (idx < 0 || idx >= mNumEntries) { - LOGW("Invalid index %d\n", idx); - return NULL; - } - - for (int ent = 0; ent < mHashTableSize; ent++) { - if (mHashTable[ent].name != NULL) { - if (idx-- == 0) - return (ZipEntryRO) (ent + kZipEntryAdj); - } - } - - return NULL; -} - -/* - * Get the useful fields from the zip entry. - * - * Returns "false" if the offsets to the fields or the contents of the fields - * appear to be bogus. - */ -bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, long* pUncompLen, - long* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const -{ - int ent = entryToIndex(entry); - if (ent < 0) - return false; - - /* - * Recover the start of the central directory entry from the filename - * pointer. - */ - const unsigned char* basePtr = (const unsigned char*)mFileMap->getDataPtr(); - const unsigned char* ptr = (const unsigned char*) mHashTable[ent].name; - size_t zipLength = mFileMap->getDataLength(); - - ptr -= kCDELen; - - int method = get2LE(ptr + kCDEMethod); - if (pMethod != NULL) - *pMethod = method; - - if (pModWhen != NULL) - *pModWhen = get4LE(ptr + kCDEModWhen); - if (pCrc32 != NULL) - *pCrc32 = get4LE(ptr + kCDECRC); - - /* - * We need to make sure that the lengths are not so large that somebody - * trying to map the compressed or uncompressed data runs off the end - * of the mapped region. - */ - unsigned long localHdrOffset = get4LE(ptr + kCDELocalOffset); - if (localHdrOffset + kLFHLen >= zipLength) { - LOGE("ERROR: bad local hdr offset in zip\n"); - return false; - } - const unsigned char* localHdr = basePtr + localHdrOffset; - off_t dataOffset = localHdrOffset + kLFHLen - + get2LE(localHdr + kLFHNameLen) + get2LE(localHdr + kLFHExtraLen); - if ((unsigned long) dataOffset >= zipLength) { - LOGE("ERROR: bad data offset in zip\n"); - return false; - } - - if (pCompLen != NULL) { - *pCompLen = get4LE(ptr + kCDECompLen); - if (*pCompLen < 0 || (size_t)(dataOffset + *pCompLen) >= zipLength) { - LOGE("ERROR: bad compressed length in zip\n"); - return false; - } - } - if (pUncompLen != NULL) { - *pUncompLen = get4LE(ptr + kCDEUncompLen); - if (*pUncompLen < 0) { - LOGE("ERROR: negative uncompressed length in zip\n"); - return false; - } - if (method == kCompressStored && - (size_t)(dataOffset + *pUncompLen) >= zipLength) - { - LOGE("ERROR: bad uncompressed length in zip\n"); - return false; - } - } - - if (pOffset != NULL) { - *pOffset = dataOffset; - } - return true; -} - -/* - * Copy the entry's filename to the buffer. - */ -int ZipFileRO::getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen) - const -{ - int ent = entryToIndex(entry); - if (ent < 0) - return -1; - - int nameLen = mHashTable[ent].nameLen; - if (bufLen < nameLen+1) - return nameLen+1; - - memcpy(buffer, mHashTable[ent].name, nameLen); - buffer[nameLen] = '\0'; - return 0; -} - -/* - * Create a new FileMap object that spans the data in "entry". - */ -FileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const -{ - /* - * TODO: the efficient way to do this is to modify FileMap to allow - * sub-regions of a file to be mapped. A reference-counting scheme - * can manage the base memory mapping. For now, we just create a brand - * new mapping off of the Zip archive file descriptor. - */ - - FileMap* newMap; - long compLen; - off_t offset; - - if (!getEntryInfo(entry, NULL, NULL, &compLen, &offset, NULL, NULL)) - return NULL; - - newMap = new FileMap(); - if (!newMap->create(mFileMap->getFileName(), mFd, offset, compLen, true)) { - newMap->release(); - return NULL; - } - - return newMap; -} - -/* - * Uncompress an entry, in its entirety, into the provided output buffer. - * - * This doesn't verify the data's CRC, which might be useful for - * uncompressed data. The caller should be able to manage it. - */ -bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const -{ - const int kSequentialMin = 32768; - bool result = false; - int ent = entryToIndex(entry); - if (ent < 0) - return -1; - - const unsigned char* basePtr = (const unsigned char*)mFileMap->getDataPtr(); - int method; - long uncompLen, compLen; - off_t offset; - - getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL); - - /* - * Experiment with madvise hint. When we want to uncompress a file, - * we pull some stuff out of the central dir entry and then hit a - * bunch of compressed or uncompressed data sequentially. The CDE - * visit will cause a limited amount of read-ahead because it's at - * the end of the file. We could end up doing lots of extra disk - * access if the file we're prying open is small. Bottom line is we - * probably don't want to turn MADV_SEQUENTIAL on and leave it on. - * - * So, if the compressed size of the file is above a certain minimum - * size, temporarily boost the read-ahead in the hope that the extra - * pair of system calls are negated by a reduction in page faults. - */ - if (compLen > kSequentialMin) - mFileMap->advise(FileMap::SEQUENTIAL); - - if (method == kCompressStored) { - memcpy(buffer, basePtr + offset, uncompLen); - } else { - if (!inflateBuffer(buffer, basePtr + offset, uncompLen, compLen)) - goto bail; - } - - if (compLen > kSequentialMin) - mFileMap->advise(FileMap::NORMAL); - - result = true; - -bail: - return result; -} - -/* - * Uncompress an entry, in its entirety, to an open file descriptor. - * - * This doesn't verify the data's CRC, but probably should. - */ -bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const -{ - bool result = false; - int ent = entryToIndex(entry); - if (ent < 0) - return -1; - - const unsigned char* basePtr = (const unsigned char*)mFileMap->getDataPtr(); - int method; - long uncompLen, compLen; - off_t offset; - - getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL); - - if (method == kCompressStored) { - ssize_t actual; - - actual = write(fd, basePtr + offset, uncompLen); - if (actual < 0) { - LOGE("Write failed: %s\n", strerror(errno)); - goto bail; - } else if (actual != uncompLen) { - LOGE("Partial write during uncompress (%d of %ld)\n", - (int)actual, uncompLen); - goto bail; - } else { - LOGI("+++ successful write\n"); - } - } else { - if (!inflateBuffer(fd, basePtr+offset, uncompLen, compLen)) - goto bail; - } - - result = true; - -bail: - return result; -} - -/* - * Uncompress "deflate" data from one buffer to another. - */ -/*static*/ bool ZipFileRO::inflateBuffer(void* outBuf, const void* inBuf, - long uncompLen, long compLen) -{ - bool result = false; - z_stream zstream; - int zerr; - - /* - * Initialize the zlib stream struct. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = (Bytef*)inBuf; - zstream.avail_in = compLen; - zstream.next_out = (Bytef*) outBuf; - zstream.avail_out = uncompLen; - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - LOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - LOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Expand data. - */ - zerr = inflate(&zstream, Z_FINISH); - if (zerr != Z_STREAM_END) { - LOGW("Zip inflate failed, zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)\n", - zerr, zstream.next_in, zstream.avail_in, - zstream.next_out, zstream.avail_out); - goto z_bail; - } - - /* paranoia */ - if ((long) zstream.total_out != uncompLen) { - LOGW("Size mismatch on inflated file (%ld vs %ld)\n", - zstream.total_out, uncompLen); - goto z_bail; - } - - result = true; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - return result; -} - -/* - * Uncompress "deflate" data from one buffer to an open file descriptor. - */ -/*static*/ bool ZipFileRO::inflateBuffer(int fd, const void* inBuf, - long uncompLen, long compLen) -{ - bool result = false; - const int kWriteBufSize = 32768; - unsigned char writeBuf[kWriteBufSize]; - z_stream zstream; - int zerr; - - /* - * Initialize the zlib stream struct. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = (Bytef*)inBuf; - zstream.avail_in = compLen; - zstream.next_out = (Bytef*) writeBuf; - zstream.avail_out = sizeof(writeBuf); - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - LOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - LOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Loop while we have more to do. - */ - do { - /* - * Expand data. - */ - zerr = inflate(&zstream, Z_NO_FLUSH); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - LOGW("zlib inflate: zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)\n", - zerr, zstream.next_in, zstream.avail_in, - zstream.next_out, zstream.avail_out); - goto z_bail; - } - - /* write when we're full or when we're done */ - if (zstream.avail_out == 0 || - (zerr == Z_STREAM_END && zstream.avail_out != sizeof(writeBuf))) - { - long writeSize = zstream.next_out - writeBuf; - int cc = write(fd, writeBuf, writeSize); - if (cc != (int) writeSize) { - LOGW("write failed in inflate (%d vs %ld)\n", cc, writeSize); - goto z_bail; - } - - zstream.next_out = writeBuf; - zstream.avail_out = sizeof(writeBuf); - } - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - /* paranoia */ - if ((long) zstream.total_out != uncompLen) { - LOGW("Size mismatch on inflated file (%ld vs %ld)\n", - zstream.total_out, uncompLen); - goto z_bail; - } - - result = true; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - return result; -} diff --git a/libs/utils/ZipUtils.cpp b/libs/utils/ZipUtils.cpp deleted file mode 100644 index bfbacfe..0000000 --- a/libs/utils/ZipUtils.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Misc zip/gzip utility functions. -// - -#define LOG_TAG "ziputil" - -#include "utils/ZipUtils.h" -#include "utils/ZipFileRO.h" -#include "utils/Log.h" - -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include <zlib.h> - -using namespace android; - -/* - * Utility function that expands zip/gzip "deflate" compressed data - * into a buffer. - * - * "fd" is an open file positioned at the start of the "deflate" data - * "buf" must hold at least "uncompressedLen" bytes. - */ -/*static*/ bool ZipUtils::inflateToBuffer(int fd, void* buf, - long uncompressedLen, long compressedLen) -{ - bool result = false; - const unsigned long kReadBufSize = 32768; - unsigned char* readBuf = NULL; - z_stream zstream; - int zerr; - unsigned long compRemaining; - - assert(uncompressedLen >= 0); - assert(compressedLen >= 0); - - readBuf = new unsigned char[kReadBufSize]; - if (readBuf == NULL) - goto bail; - compRemaining = compressedLen; - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = (Bytef*) buf; - zstream.avail_out = uncompressedLen; - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - LOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - LOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Loop while we have data. - */ - do { - unsigned long getSize; - - /* read as much as we can */ - if (zstream.avail_in == 0) { - getSize = (compRemaining > kReadBufSize) ? - kReadBufSize : compRemaining; - LOGV("+++ reading %ld bytes (%ld left)\n", - getSize, compRemaining); - - int cc = read(fd, readBuf, getSize); - if (cc != (int) getSize) { - LOGD("inflate read failed (%d vs %ld)\n", - cc, getSize); - goto z_bail; - } - - compRemaining -= getSize; - - zstream.next_in = readBuf; - zstream.avail_in = getSize; - } - - /* uncompress the data */ - zerr = inflate(&zstream, Z_NO_FLUSH); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - LOGD("zlib inflate call failed (zerr=%d)\n", zerr); - goto z_bail; - } - - /* output buffer holds all, so no need to write the output */ - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - if ((long) zstream.total_out != uncompressedLen) { - LOGW("Size mismatch on inflated file (%ld vs %ld)\n", - zstream.total_out, uncompressedLen); - goto z_bail; - } - - // success! - result = true; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - delete[] readBuf; - return result; -} - -/* - * Utility function that expands zip/gzip "deflate" compressed data - * into a buffer. - * - * (This is a clone of the previous function, but it takes a FILE* instead - * of an fd. We could pass fileno(fd) to the above, but we can run into - * trouble when "fp" has a different notion of what fd's file position is.) - * - * "fp" is an open file positioned at the start of the "deflate" data - * "buf" must hold at least "uncompressedLen" bytes. - */ -/*static*/ bool ZipUtils::inflateToBuffer(FILE* fp, void* buf, - long uncompressedLen, long compressedLen) -{ - bool result = false; - const unsigned long kReadBufSize = 32768; - unsigned char* readBuf = NULL; - z_stream zstream; - int zerr; - unsigned long compRemaining; - - assert(uncompressedLen >= 0); - assert(compressedLen >= 0); - - readBuf = new unsigned char[kReadBufSize]; - if (readBuf == NULL) - goto bail; - compRemaining = compressedLen; - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = (Bytef*) buf; - zstream.avail_out = uncompressedLen; - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - LOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - LOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Loop while we have data. - */ - do { - unsigned long getSize; - - /* read as much as we can */ - if (zstream.avail_in == 0) { - getSize = (compRemaining > kReadBufSize) ? - kReadBufSize : compRemaining; - LOGV("+++ reading %ld bytes (%ld left)\n", - getSize, compRemaining); - - int cc = fread(readBuf, getSize, 1, fp); - if (cc != (int) getSize) { - LOGD("inflate read failed (%d vs %ld)\n", - cc, getSize); - goto z_bail; - } - - compRemaining -= getSize; - - zstream.next_in = readBuf; - zstream.avail_in = getSize; - } - - /* uncompress the data */ - zerr = inflate(&zstream, Z_NO_FLUSH); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - LOGD("zlib inflate call failed (zerr=%d)\n", zerr); - goto z_bail; - } - - /* output buffer holds all, so no need to write the output */ - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - if ((long) zstream.total_out != uncompressedLen) { - LOGW("Size mismatch on inflated file (%ld vs %ld)\n", - zstream.total_out, uncompressedLen); - goto z_bail; - } - - // success! - result = true; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - delete[] readBuf; - return result; -} - -/* - * Look at the contents of a gzip archive. We want to know where the - * data starts, and how long it will be after it is uncompressed. - * - * We expect to find the CRC and length as the last 8 bytes on the file. - * This is a pretty reasonable thing to expect for locally-compressed - * files, but there's a small chance that some extra padding got thrown - * on (the man page talks about compressed data written to tape). We - * don't currently deal with that here. If "gzip -l" whines, we're going - * to fail too. - * - * On exit, "fp" is pointing at the start of the compressed data. - */ -/*static*/ bool ZipUtils::examineGzip(FILE* fp, int* pCompressionMethod, - long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32) -{ - enum { // flags - FTEXT = 0x01, - FHCRC = 0x02, - FEXTRA = 0x04, - FNAME = 0x08, - FCOMMENT = 0x10, - }; - int ic; - int method, flags; - int i; - - ic = getc(fp); - if (ic != 0x1f || getc(fp) != 0x8b) - return false; // not gzip - method = getc(fp); - flags = getc(fp); - - /* quick sanity checks */ - if (method == EOF || flags == EOF) - return false; - if (method != ZipFileRO::kCompressDeflated) - return false; - - /* skip over 4 bytes of mod time, 1 byte XFL, 1 byte OS */ - for (i = 0; i < 6; i++) - (void) getc(fp); - /* consume "extra" field, if present */ - if ((flags & FEXTRA) != 0) { - int len; - - len = getc(fp); - len |= getc(fp) << 8; - while (len-- && getc(fp) != EOF) - ; - } - /* consume filename, if present */ - if ((flags & FNAME) != 0) { - do { - ic = getc(fp); - } while (ic != 0 && ic != EOF); - } - /* consume comment, if present */ - if ((flags & FCOMMENT) != 0) { - do { - ic = getc(fp); - } while (ic != 0 && ic != EOF); - } - /* consume 16-bit header CRC, if present */ - if ((flags & FHCRC) != 0) { - (void) getc(fp); - (void) getc(fp); - } - - if (feof(fp) || ferror(fp)) - return false; - - /* seek to the end; CRC and length are in the last 8 bytes */ - long curPosn = ftell(fp); - unsigned char buf[8]; - fseek(fp, -8, SEEK_END); - *pCompressedLen = ftell(fp) - curPosn; - - if (fread(buf, 1, 8, fp) != 8) - return false; - /* seek back to start of compressed data */ - fseek(fp, curPosn, SEEK_SET); - - *pCompressionMethod = method; - *pCRC32 = ZipFileRO::get4LE(&buf[0]); - *pUncompressedLen = ZipFileRO::get4LE(&buf[4]); - - return true; -} - diff --git a/libs/utils/characterData.h b/libs/utils/characterData.h deleted file mode 100644 index e931d99..0000000 --- a/libs/utils/characterData.h +++ /dev/null @@ -1,730 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Automatically generated on 07-11-2006 by make-CharacterDataC -// DO NOT EDIT DIRECTLY -namespace CharacterData { - - // Structure containing an array of ranges - struct Range { - int length; - const uint32_t* array; - }; - - // For Latin1 characters just index into this array to get the index and decomposition - static const uint16_t LATIN1_DATA[] = { - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0002, 0x0003, 0x0002, 0x0004, 0x0003, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0003, 0x0003, 0x0003, 0x0002, - 0x0005, 0x0006, 0x0006, 0x0007, 0x0008, 0x0007, 0x0006, 0x0006, - 0x0009, 0x000A, 0x0006, 0x000B, 0x000C, 0x000D, 0x000C, 0x000C, - 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, - 0x0016, 0x0017, 0x000C, 0x0006, 0x0018, 0x0019, 0x001A, 0x0006, - 0x0006, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, - 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, - 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, - 0x0032, 0x0033, 0x0034, 0x0035, 0x0006, 0x0036, 0x0037, 0x0038, - 0x0037, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0035, 0x0019, 0x0036, 0x0019, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0003, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x5853, 0x0006, 0x0008, 0x0008, 0x0008, 0x0008, 0x0054, 0x0054, - 0x1037, 0x0054, 0x7855, 0x0056, 0x0019, 0x0057, 0x0054, 0x1037, - 0x0058, 0x0059, 0x785A, 0x785B, 0x1037, 0x105C, 0x0054, 0x0006, - 0x1037, 0x785D, 0x7855, 0x005E, 0x305F, 0x305F, 0x305F, 0x0006, - 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0060, 0x0860, - 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, - 0x0060, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0019, - 0x0060, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0060, 0x0055, - 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0061, 0x0861, - 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, - 0x0061, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0019, - 0x0061, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0061, 0x0862 - }; - - // Each of these arrays is stripped into ranges. In order to build the arrays, each - // codepoint was bit-shifted so that even and odd characters were separated into different - // arrays. The identifier of each array is the top byte after bit-shifting. - // The numbers stored in the array are the bit-shifted codepoint, the decomposition, and an - // index into another array of all possible packed data values. The top 16 bits are the - // codepoint and the bottom 16 are the decomposition and index. The top 5 bits for the decomposition - // and the rest for the index. - static const uint32_t a0[] = { - 0x00800863, 0x00880063, 0x00890863, 0x00930063, 0x00940863, 0x00980864, 0x00991063, 0x009A0863, - 0x009C0055, 0x009D0865, 0x00A01065, 0x00A10065, 0x00A20865, 0x00A50063, 0x00A60863, 0x00A90063, - 0x00AA0863, 0x00B30063, 0x00B40863, 0x00BC0866, 0x00BD0865, 0x00C00055, 0x00C10063, 0x00C30067, - 0x00C40065, 0x00C50068, 0x00C60065, 0x00C70069, 0x00C8006A, 0x00C90065, 0x00CA006B, 0x00CB006C, - 0x00CC0063, 0x00CD006D, 0x00CE006C, 0x00CF006E, 0x00D00863, 0x00D10063, 0x00D3006F, 0x00D40065, - 0x00D50055, 0x00D60063, 0x00D7006F, 0x00D80865, 0x00D90070, 0x00DA0065, 0x00DC0063, 0x00DD0055, - 0x00DE0063, 0x00DF0055, 0x00E00071, 0x00E21072, 0x00E31073, 0x00E41074, 0x00E51072, 0x00E61073, - 0x00E70865, 0x00EF0863, 0x00F20063, 0x00F30863, 0x00F80855, 0x00F91074, 0x00FA0863, 0x00FB0075, - 0x00FC0863, 0x010E0063, 0x010F0863, 0x01100076, 0x01110063, 0x01130863, 0x011A0055, 0x011D0077, - 0x011E0065, 0x011F0077, 0x01200055, 0x01210078, 0x01280055, 0x012A0079, 0x012B007A, 0x012C0055, - 0x0130007A, 0x01310055, 0x0134007B, 0x01350055, 0x0139007C, 0x013A0055, 0x0140007D, 0x01410055, - 0x0144007D, 0x0145007E, 0x01460055, 0x0149007F, 0x014A0080, 0x014B0055, 0x01587881, 0x015D0082, - 0x015E0081, 0x01610037, 0x01630082, 0x01680081, 0x01690037, 0x016C1037, 0x016F0037, 0x01707881, - 0x01730037, 0x01770081, 0x01780037, 0x01800083, 0x01A00883, 0x01A10083, 0x01A20883, 0x01A30083, - 0x01B80078, 0x01BA0837, 0x01BB0078, 0x01BD1081, 0x01BE0078, 0x01BF0806, 0x01C00078, 0x01C21037, - 0x01C30884, 0x01C40885, 0x01C60886, 0x01C70887, 0x01C80855, 0x01C90060, 0x01D10078, 0x01D20060, - 0x01D50860, 0x01D60888, 0x01D70889, 0x01D80855, 0x01D90061, 0x01E1008A, 0x01E20061, 0x01E50861, - 0x01E6088B, 0x01E7088C, 0x01E8108D, 0x01E91077, 0x01EA0877, 0x01EB108E, 0x01EC0063, 0x01F8108F, - 0x01F91090, 0x01FA1091, 0x01FB0019, 0x01FC0065, 0x01FD0063, 0x01FE0055, 0x01FF0077, 0x02000892, - 0x02010092, 0x02060892, 0x02080060, 0x02180061, 0x02280893, 0x02290093, 0x022E0893, 0x02300063, - 0x023B0863, 0x023C0063, 0x02410094, 0x02420083, 0x02440095, 0x02450063, 0x02600077, 0x02610865, - 0x02620065, 0x02680863, 0x026A0063, 0x026B0863, 0x026C0063, 0x026D0863, 0x02700063, 0x02710863, - 0x02740063, 0x02750863, 0x027B0063, 0x027C0863, 0x027D0078, 0x02800063, 0x02880078, 0x02990096, - 0x02AC0078, 0x02AD0097, 0x02B00078, 0x02B10098, 0x02C40078, 0x02C50099, 0x02C60078, 0x02C90083, - 0x02DD0078, 0x02DE0083, 0x02DF009A, 0x02E10083, 0x02E3009A, 0x02E40078, 0x02E8009B, 0x02F60078, - 0x02F8009B, 0x02FA009A, 0x02FB0078, 0x0300009C, 0x03020078, 0x0306000C, 0x03070054, 0x03080083, - 0x030B0078, 0x030F009D, 0x03100078, 0x0311089E, 0x0314009E, 0x031E0078, 0x0320009F, 0x0321009E, - 0x03260083, 0x033000A0, 0x033100A1, 0x033200A2, 0x033300A3, 0x033400A4, 0x03350007, 0x033600A5, - 0x0337009E, 0x03380083, 0x0339009E, 0x033B109E, 0x033D009E, 0x0360089E, 0x0362009E, 0x036A009D, - 0x036B0083, 0x036F0095, 0x03700083, 0x0373009F, 0x03740083, 0x0377009E, 0x0378000E, 0x03790010, - 0x037A0012, 0x037B0014, 0x037C0016, 0x037D009E, 0x037F00A6, 0x0380009D, 0x03870078, 0x0388009E, - 0x03980083, 0x03A60078, 0x03A7009E, 0x03B70078, 0x03C0009E, 0x03D30083, 0x03D90078, 0x04810083, - 0x04820071, 0x049A0871, 0x049B0071, 0x049D0078, 0x049E0083, 0x049F00A7, 0x04A10083, 0x04A500A7, - 0x04A70078, 0x04A80071, 0x04A90083, 0x04AB0078, 0x04AC0871, 0x04B00071, 0x04B10083, 0x04B20097, - 0x04B300A8, 0x04B400A9, 0x04B500AA, 0x04B600AB, 0x04B700AC, 0x04B80097, 0x04B90078, 0x04C100A7, - 0x04C20078, 0x04C30071, 0x04C70078, 0x04C80071, 0x04C90078, 0x04CA0071, 0x04DA0078, 0x04DB0071, - 0x04DD0078, 0x04DE0083, 0x04DF00A7, 0x04E10083, 0x04E30078, 0x04E400A7, 0x04E50078, 0x04E608A7, - 0x04E70071, 0x04E80078, 0x04EE0871, 0x04EF0078, 0x04F00071, 0x04F10083, 0x04F20078, 0x04F300A8, - 0x04F400A9, 0x04F500AA, 0x04F600AB, 0x04F700AC, 0x04F80071, 0x04F90008, 0x04FA00AD, 0x04FB00AE, - 0x04FC00AF, 0x04FD0094, 0x04FE0078, 0x05010083, 0x05020078, 0x05030071, 0x05060078, 0x05080071, - 0x05090078, 0x050A0071, 0x051A0078, 0x051B0871, 0x051C0071, 0x051D0078, 0x051E0083, 0x051F00A7, - 0x05210083, 0x05220078, 0x05240083, 0x05250078, 0x05260083, 0x05270078, 0x052D0871, 0x052E0071, - 0x052F0871, 0x05300078, 0x053300A8, 0x053400A9, 0x053500AA, 0x053600AB, 0x053700AC, 0x05380083, - 0x05390071, 0x053B0078, 0x05410083, 0x05420078, 0x05430071, 0x05470078, 0x05480071, 0x05490078, - 0x054A0071, 0x055A0078, 0x055B0071, 0x055D0078, 0x055E0083, 0x055F00A7, 0x05610083, 0x05630078, - 0x05640083, 0x05650078, 0x056600A7, 0x05670078, 0x05680071, 0x05690078, 0x05700071, 0x05710083, - 0x05720078, 0x057300A8, 0x057400A9, 0x057500AA, 0x057600AB, 0x057700AC, 0x05780078, 0x058100A7, - 0x05820078, 0x05830071, 0x05870078, 0x05880071, 0x05890078, 0x058A0071, 0x059A0078, 0x059B0071, - 0x059D0078, 0x059E0083, 0x059F00A7, 0x05A10083, 0x05A20078, 0x05A408A7, 0x05A50078, 0x05A608A7, - 0x05A70078, 0x05AB0083, 0x05AC0078, 0x05AE0871, 0x05AF0078, 0x05B00071, 0x05B10078, 0x05B300A8, - 0x05B400A9, 0x05B500AA, 0x05B600AB, 0x05B700AC, 0x05B80094, 0x05B90078, 0x05C10083, 0x05C20078, - 0x05C30071, 0x05C60078, 0x05C70071, 0x05CA0871, 0x05CB0078, 0x05CD0071, 0x05D00078, 0x05D20071, - 0x05D30078, 0x05D40071, 0x05D60078, 0x05D70071, 0x05DD0078, 0x05DF00A7, 0x05E00083, 0x05E100A7, - 0x05E20078, 0x05E300A7, 0x05E508A7, 0x05E70078, 0x05F300A8, 0x05F400A9, 0x05F500AA, 0x05F600AB, - 0x05F700AC, 0x05F800B0, 0x05F900B1, 0x05FA0054, 0x05FE0078, 0x060100A7, 0x06020078, 0x06030071, - 0x061A0078, 0x061B0071, 0x061D0078, 0x061F0083, 0x062100A7, 0x06230083, 0x06240883, 0x06250083, - 0x06270078, 0x062B0083, 0x062C0078, 0x06300071, 0x06310078, 0x063300A8, 0x063400A9, 0x063500AA, - 0x063600AB, 0x063700AC, 0x06380078, 0x064100A7, 0x06420078, 0x06430071, 0x065A0078, 0x065B0071, - 0x065D0078, 0x065E0083, 0x065F00A7, 0x066008A7, 0x066100A7, 0x066300B2, 0x066408A7, 0x06660083, - 0x06670078, 0x066B00A7, 0x066C0078, 0x066F0071, 0x06710078, 0x067300A8, 0x067400A9, 0x067500AA, - 0x067600AB, 0x067700AC, 0x06780078, 0x068100A7, 0x06820078, 0x06830071, 0x069D0078, 0x069F00A7, - 0x06A10083, 0x06A20078, 0x06A300A7, 0x06A508A7, 0x06A70078, 0x06B00071, 0x06B10078, 0x06B300A8, - 0x06B400A9, 0x06B500AA, 0x06B600AB, 0x06B700AC, 0x06B80078, 0x06C100A7, 0x06C20078, 0x06C30071, - 0x06CC0078, 0x06CD0071, 0x06D90078, 0x06DA0071, 0x06DE0078, 0x06E00071, 0x06E40078, 0x06E50083, - 0x06E60078, 0x06E800A7, 0x06E90083, 0x06EC00A7, 0x06ED08A7, 0x06F00078, 0x06F900A7, 0x06FA0097, - 0x06FB0078, 0x07010071, 0x071A0083, 0x071E0078, 0x07200071, 0x07230081, 0x07240083, 0x072800A8, - 0x072900A9, 0x072A00AA, 0x072B00AB, 0x072C00AC, 0x072D0097, 0x072E0078, 0x07410071, 0x07430078, - 0x07440071, 0x07460078, 0x074A0071, 0x074C0078, 0x074D0071, 0x07500078, 0x07510071, 0x07520078, - 0x07550071, 0x07560078, 0x07570071, 0x075A0083, 0x075D0078, 0x075E0083, 0x075F0078, 0x07600071, - 0x07630081, 0x07640083, 0x07670078, 0x076800A8, 0x076900A9, 0x076A00AA, 0x076B00AB, 0x076C00AC, - 0x076D0078, 0x076E1071, 0x076F0078, 0x07800071, 0x07810094, 0x07820097, 0x07865897, 0x07870097, - 0x078A0094, 0x078C0083, 0x078D0094, 0x079000A8, 0x079100A9, 0x079200AA, 0x079300AB, 0x079400AC, - 0x079500B3, 0x079A0094, 0x079D00B4, 0x079F00A7, 0x07A00071, 0x07A40078, 0x07A50071, 0x07A90871, - 0x07AA0071, 0x07AE0871, 0x07AF0071, 0x07B60078, 0x07B90083, 0x07BB0883, 0x07BD0083, 0x07C40071, - 0x07C60078, 0x07C80083, 0x07CC0078, 0x07CD0083, 0x07D10883, 0x07D20083, 0x07D60883, 0x07D70083, - 0x07DF0094, 0x07E30083, 0x07E40094, 0x07E70078, 0x07E80097, 0x07E90078, 0x08000071, 0x08110078, - 0x08120071, 0x08130871, 0x08140078, 0x08150071, 0x081600A7, 0x08170083, 0x081A0078, 0x081B0083, - 0x081C00A7, 0x081D0078, 0x082000A8, 0x082100A9, 0x082200AA, 0x082300AB, 0x082400AC, 0x08250097, - 0x08280071, 0x082B00A7, 0x082C0083, 0x082D0078, 0x085000B5, 0x08630078, 0x08680071, 0x087E7881, - 0x087F0078, 0x08800071, 0x08AD0078, 0x08B00071, 0x08D20078, 0x08D40071, 0x08FD0078, 0x09000071, - 0x09270078, 0x09280071, 0x092F0078, 0x09300071, 0x09470078, 0x09480071, 0x095B0078, 0x095C0071, - 0x09630078, 0x09640071, 0x098B0078, 0x098C0071, 0x09AE0078, 0x09B00094, 0x09B10097, 0x09B500B6, - 0x09B600B7, 0x09B700B8, 0x09B800B9, 0x09B900B0, 0x09BA00BA, 0x09BB00BB, 0x09BC00BC, 0x09BD00BD, - 0x09BE00BE, 0x09BF0078, 0x09C00071, 0x09C80054, 0x09CD0078, 0x09D00071, 0x09FB0078, 0x0A010071, - 0x0B370097, 0x0B380071, 0x0B3C0078, 0x0B400005, 0x0B410071, 0x0B4E00BF, 0x0B4F0078, 0x0B500071, - 0x0B760097, 0x0B7700C0, 0x0B7800C1, 0x0B790078, 0x0B800071, 0x0B890083, 0x0B8B0078, 0x0B900071, - 0x0B990083, 0x0B9B0097, 0x0B9C0078, 0x0BA00071, 0x0BA90083, 0x0BAA0078, 0x0BB00071, 0x0BB90083, - 0x0BBA0078, 0x0BC00071, 0x0BDA00C2, 0x0BDB00A7, 0x0BDC0083, 0x0BDF00A7, 0x0BE30083, 0x0BE400A7, - 0x0BE50083, 0x0BEA0097, 0x0BEE0071, 0x0BEF0078, 0x0BF000A8, 0x0BF100A9, 0x0BF200AA, 0x0BF300AB, - 0x0BF400AC, 0x0BF50078, 0x0BF800C3, 0x0BF900C4, 0x0BFA00C5, 0x0BFB00C6, 0x0BFC00C7, 0x0BFD0078, - 0x0C000006, 0x0C030099, 0x0C040006, 0x0C060083, 0x0C070005, 0x0C0800A8, 0x0C0900A9, 0x0C0A00AA, - 0x0C0B00AB, 0x0C0C00AC, 0x0C0D0078, 0x0C100071, 0x0C3C0078, 0x0C400071, 0x0C550078, 0x0C800071, - 0x0C8F0078, 0x0C900083, 0x0C9200A7, 0x0C940083, 0x0C9500C8, 0x0C960078, 0x0C9800A7, 0x0C990083, - 0x0C9A00A7, 0x0C9D0083, 0x0C9E0078, 0x0CA00054, 0x0CA10078, 0x0CA20006, 0x0CA300A8, 0x0CA400A9, - 0x0CA500AA, 0x0CA600AB, 0x0CA700AC, 0x0CA80071, 0x0CB70078, 0x0CB80071, 0x0CBB0078, 0x0CC00071, - 0x0CD50078, 0x0CD800A7, 0x0CE10071, 0x0CE400A7, 0x0CE50078, 0x0CE800A8, 0x0CE900A9, 0x0CEA00AA, - 0x0CEB00AB, 0x0CEC00AC, 0x0CED0078, 0x0CEF0006, 0x0CF00054, 0x0D000071, 0x0D0C0083, 0x0D0D00A7, - 0x0D0E0078, 0x0D0F0097, 0x0D100078, 0x0E800055, 0x0E967881, 0x0EA70081, 0x0EA87881, 0x0EB17055, - 0x0EB60055, 0x0EBC7881, 0x0EBD0055, 0x0ECE7881, 0x0EE00083, 0x0EE20078, 0x0F000863, 0x0F4B0855, - 0x0F4D1055, 0x0F4E0078, 0x0F500863, 0x0F7D0078, 0x0F8008C9, 0x0F8408CA, 0x0F8808C9, 0x0F8B0078, - 0x0F8C08CA, 0x0F8F0078, 0x0F9008C9, 0x0F9408CA, 0x0F9808C9, 0x0F9C08CA, 0x0FA008C9, 0x0FA30078, - 0x0FA408CA, 0x0FA70078, 0x0FA80855, 0x0FAC0078, 0x0FB008C9, 0x0FB408CA, 0x0FB808CB, 0x0FB908CC, - 0x0FBB08CD, 0x0FBC08CE, 0x0FBD08CF, 0x0FBE08D0, 0x0FBF0078, 0x0FC008C9, 0x0FC408D1, 0x0FC808C9, - 0x0FCC08D1, 0x0FD008C9, 0x0FD408D1, 0x0FD808C9, 0x0FD90855, 0x0FDC08CA, 0x0FDD08D2, 0x0FDE08D3, - 0x0FDF08D4, 0x0FE01037, 0x0FE10855, 0x0FE408D5, 0x0FE608D3, 0x0FE70837, 0x0FE808C9, 0x0FE90855, - 0x0FEA0078, 0x0FEB0855, 0x0FEC08CA, 0x0FED08D6, 0x0FEE0078, 0x0FEF0837, 0x0FF008C9, 0x0FF10855, - 0x0FF408CA, 0x0FF508D7, 0x0FF608D8, 0x0FF70837, 0x0FF80078, 0x0FF90855, 0x0FFC08D9, 0x0FFD08DA, - 0x0FFE08D3, 0x0FFF1037, 0x10000805, 0x10011005, 0x10060057, 0x100700C2, 0x10080099, 0x100B0006, - 0x100C00DB, 0x100D00B4, 0x100E00DB, 0x100F00B4, 0x10100006, 0x10121006, 0x101400DC, 0x101500DD, - 0x101600DE, 0x101700DF, 0x10180007, 0x101A1007, 0x101B1006, 0x101C0006, 0x101D00E0, 0x101E1006, - 0x10200038, 0x10210006, 0x102200E1, 0x1023000A, 0x10241006, 0x10250006, 0x10290019, 0x102A0038, - 0x102B0006, 0x10300057, 0x10320078, 0x10350057, 0x103878E2, 0x10390078, 0x103A78E3, 0x103B78E4, - 0x103C78E5, 0x103D780B, 0x103E7819, 0x103F780A, 0x104070E2, 0x1041705A, 0x104270E3, 0x104370E4, - 0x104470E5, 0x1045700B, 0x10467019, 0x1047700A, 0x10487081, 0x104B0078, 0x10500008, 0x10541008, - 0x10550008, 0x105B0078, 0x10680083, 0x106F0095, 0x10730083, 0x10760078, 0x10801054, 0x10812877, - 0x10820054, 0x10831054, 0x10840054, 0x10852855, 0x10862877, 0x10872855, 0x10882877, 0x108A0054, - 0x108B1054, 0x108C0054, 0x108D2877, 0x108F0054, 0x10907854, 0x10922877, 0x109308E6, 0x10942877, - 0x109508E7, 0x10962877, 0x10970058, 0x10982877, 0x10990054, 0x109A2855, 0x109B1071, 0x109D0054, - 0x109E2855, 0x109F2877, 0x10A028E8, 0x10A10019, 0x10A32855, 0x10A50054, 0x10A70078, 0x10AA305F, - 0x10B010E9, 0x10B110EA, 0x10B210EB, 0x10B310EC, 0x10B410ED, 0x10B510EE, 0x10B610EF, 0x10B710F0, - 0x10B810F1, 0x10B910F2, 0x10BA10F3, 0x10BB10F4, 0x10BC10F5, 0x10BD10F6, 0x10BE10F7, 0x10BF10F8, - 0x10C000F9, 0x10C100FA, 0x10C20078, 0x10C80019, 0x10CB0054, 0x10CD0819, 0x10CE0054, 0x10D00019, - 0x10D10054, 0x10D30019, 0x10D40054, 0x10D70819, 0x10D80054, 0x10E70819, 0x10E80054, 0x10E90019, - 0x10EB0054, 0x10FA0019, 0x110100E8, 0x110208E8, 0x11030019, 0x110400FB, 0x110608FC, 0x11070019, - 0x1109000B, 0x110A0019, 0x110B00E8, 0x110C0019, 0x110D00E8, 0x110F0019, 0x111000E8, 0x111208E8, - 0x11140019, 0x111610E8, 0x111700E8, 0x111810E8, 0x111900E8, 0x111A0019, 0x111E00FD, 0x111F00E8, - 0x112208E8, 0x112300E8, 0x11270019, 0x112900FD, 0x112B0019, 0x113008E8, 0x113200FD, 0x11360019, - 0x113708FD, 0x113900FD, 0x113A08FD, 0x113B00FD, 0x113C08FD, 0x113D00FD, 0x114008FD, 0x114100FD, - 0x114208FD, 0x114300FD, 0x114408FD, 0x114500FD, 0x114600E8, 0x11470019, 0x114800FE, 0x114A0019, - 0x114C00FF, 0x114D0019, 0x115100FD, 0x11520019, 0x11530100, 0x11540101, 0x115500E8, 0x115608E8, - 0x115800FD, 0x115C00E8, 0x115D0019, 0x115F00E8, 0x11600019, 0x116500FE, 0x11670019, 0x116800FD, - 0x11690019, 0x116B00FD, 0x117008FD, 0x117200FD, 0x117508FD, 0x11770019, 0x117800FD, 0x11790102, - 0x117B0103, 0x117C00E8, 0x117D0104, 0x117F0105, 0x11800054, 0x118400FD, 0x11860054, 0x119000E8, - 0x11910054, 0x1195080A, 0x11960054, 0x119B0094, 0x11BE0019, 0x11BF0054, 0x11CE0019, 0x11DA00B4, - 0x11DB0006, 0x11DC0054, 0x11EE0078, 0x12000054, 0x12140078, 0x12200054, 0x12260078, 0x12301906, - 0x12311907, 0x12321908, 0x12331909, 0x1234190A, 0x1235190B, 0x1236190C, 0x1237190D, 0x1238190E, - 0x1239190F, 0x123A1106, 0x123B1107, 0x123C1108, 0x123D1109, 0x123E110A, 0x123F110B, 0x1240110C, - 0x1241110D, 0x1242110E, 0x1243110F, 0x1244105D, 0x1245105B, 0x12461110, 0x12471111, 0x12481112, - 0x12491113, 0x124A1114, 0x124B1115, 0x124C1116, 0x124D1117, 0x124E1094, 0x125B1918, 0x12681919, - 0x127518C3, 0x1276011A, 0x1277011B, 0x1278011C, 0x1279011D, 0x127A011E, 0x127B00C4, 0x127C00C5, - 0x127D00C6, 0x127E00C7, 0x127F011F, 0x12800054, 0x12FC0019, 0x13000054, 0x134F0078, 0x13500054, - 0x13560094, 0x13570054, 0x13590078, 0x13810054, 0x13850078, 0x13860054, 0x13940078, 0x13950054, - 0x13A60078, 0x13A80054, 0x13AA0078, 0x13AB0054, 0x13B00078, 0x13B10054, 0x13B40009, 0x13BB0106, - 0x13BC0107, 0x13BD0108, 0x13BE0109, 0x13BF010A, 0x13C00106, 0x13C10107, 0x13C20108, 0x13C30109, - 0x13C4010A, 0x13C50106, 0x13C60107, 0x13C70108, 0x13C80109, 0x13C9010A, 0x13CA0054, 0x13CB0078, - 0x13CC0054, 0x13D80078, 0x13D90054, 0x13E000E8, 0x13E10019, 0x13E200FE, 0x13E3000A, 0x13E40078, - 0x13E80019, 0x13EA00E8, 0x13EB00FE, 0x13EC0019, 0x13EE00E8, 0x13EF00FE, 0x13F00019, 0x13F100FD, - 0x13F30009, 0x13F60078, 0x13F80019, 0x14000094, 0x14800019, 0x14C2000A, 0x14C70120, 0x14C80121, - 0x14C9000A, 0x14CD0019, 0x14CE00E8, 0x14D80019, 0x14DC0122, 0x14DD0019, 0x14E000FD, 0x14E100E8, - 0x14E200FD, 0x14E30019, 0x14E700E8, 0x14E800FE, 0x14EA00FD, 0x14EB0019, 0x14EC0009, 0x14EE00E8, - 0x14EF0019, 0x14F200E8, 0x14F30019, 0x14F400E8, 0x14F50019, 0x14FA00E8, 0x14FC00FD, 0x14FD0019, - 0x14FE0009, 0x14FF0019, 0x150500E8, 0x150610E8, 0x150700E8, 0x15110019, 0x151200E8, 0x15140019, - 0x151600FE, 0x15180019, 0x151A00FD, 0x151B0019, 0x151E00FD, 0x151F00E8, 0x15200019, 0x152C00E8, - 0x152D0019, 0x153200FD, 0x15330019, 0x153500E8, 0x15370019, 0x153800E8, 0x15390019, 0x153A10E8, - 0x153B1019, 0x153C0019, 0x153D00FE, 0x153E00E8, 0x153F00FE, 0x154300E8, 0x154600FE, 0x154700E8, - 0x154900FE, 0x154F00E8, 0x155100FE, 0x15520019, 0x155300FD, 0x15570019, 0x155800FE, 0x155900E8, - 0x155A00FE, 0x155B00E8, 0x155E00FE, 0x156400E8, 0x156700FE, 0x156C0019, 0x156E08E8, 0x156F0123, - 0x15700019, 0x157100E8, 0x15720124, 0x157300E8, 0x15740019, 0x157600FD, 0x157700E8, 0x15780019, - 0x157C00FE, 0x157E0019, 0x15800054, 0x158A0078, 0x16000096, 0x16180098, 0x16300078, 0x16400063, - 0x16720055, 0x16730054, 0x16760078, 0x167D0006, 0x16800125, 0x16930078, 0x16980071, 0x16B30078, - 0x16C00071, 0x16CC0078, 0x16D00071, 0x16F00078, 0x17000006, 0x17010126, 0x17030006, 0x170500E0, - 0x17060126, 0x17070006, 0x170C0078, 0x170E0126, 0x170F0078, 0x17400054, 0x174D0078, 0x174E0054, - 0x177A0078, 0x17801054, 0x17EB0078, 0x17F80054, 0x17FE0078, 0x18008805, 0x18010006, 0x18020054, - 0x18030071, 0x18040009, 0x18090054, 0x180A0009, 0x180E0099, 0x180F00BF, 0x18100054, 0x18110127, - 0x18120128, 0x18130129, 0x1814012A, 0x18150083, 0x18180099, 0x18190081, 0x181B1054, 0x181C112B, - 0x181D112C, 0x181E0071, 0x181F0054, 0x18200078, 0x18210071, 0x18260871, 0x18320071, 0x18380871, - 0x18390071, 0x183A0871, 0x183C0071, 0x183D0871, 0x183F0071, 0x184A0871, 0x184B0071, 0x184C0078, - 0x184D0083, 0x184E1037, 0x184F0881, 0x18500099, 0x18510071, 0x18560871, 0x18620071, 0x18680871, - 0x18690071, 0x186A0871, 0x186C0071, 0x186D0871, 0x186F0071, 0x187A0871, 0x187B0071, 0x187C0871, - 0x187E0081, 0x187F0881, 0x18800078, 0x18830071, 0x18970078, 0x18991071, 0x18C80094, 0x18C978AD, - 0x18CA78AE, 0x18CB7894, 0x18D00071, 0x18DC0078, 0x18E00054, 0x18E80078, 0x18F80071, 0x19001094, - 0x190F1054, 0x191010AD, 0x191110AE, 0x1912112D, 0x1913112E, 0x1914112F, 0x19151094, 0x19220078, - 0x19286854, 0x19291930, 0x192A1931, 0x192B1932, 0x192C1933, 0x192D1934, 0x192E1935, 0x192F1936, - 0x19301894, 0x193E1854, 0x194018AD, 0x194118AE, 0x1942192D, 0x1943192E, 0x1944192F, 0x19451894, - 0x19591937, 0x195A1938, 0x195B1939, 0x195C193A, 0x195D193B, 0x195E193C, 0x195F193D, 0x19601094, - 0x19666854, 0x19681894, 0x19806894, 0x19AC1094, 0x19B96894, 0x19BC6854, 0x19BE6894, 0x19EF6854, - 0x19F01094, 0x1A000071, 0x26DB0078, 0x26E00054, 0x27000071, 0x4FDE0078, 0x50000071, 0x52470078, - 0x52480054, 0x52640078, 0x53800037, 0x538C0078, 0x54000071, 0x540100C8, 0x54020071, 0x54030083, - 0x54040071, 0x541200A7, 0x54130083, 0x54140054, 0x54160078, 0x56000071, 0x6BD20078, 0x6C00013E, - 0x7000013F, 0x7C800871, 0x7D070071, 0x7D080871, 0x7D0A0071, 0x7D0B0871, 0x7D120071, 0x7D130871, - 0x7D140071, 0x7D150871, 0x7D170078, 0x7D180871, 0x7D360078, 0x7D380871, 0x7D6D0078, 0x7D801055, - 0x7D840078, 0x7D8A1055, 0x7D8C0078, 0x7D8F0083, 0x7D90289B, 0x7D95089B, 0x7DA10078, 0x7DA2089B, - 0x7DA8409E, 0x7DAA389E, 0x7DAB409E, 0x7DAC389E, 0x7DAD409E, 0x7DAE389E, 0x7DAF409E, 0x7DB0389E, - 0x7DB1409E, 0x7DB2389E, 0x7DB3409E, 0x7DB4389E, 0x7DB5409E, 0x7DB6389E, 0x7DB7409E, 0x7DB8389E, - 0x7DB9409E, 0x7DBA389E, 0x7DBB409E, 0x7DBC389E, 0x7DBD409E, 0x7DBE389E, 0x7DBF409E, 0x7DC0389E, - 0x7DC1409E, 0x7DC8389E, 0x7DC9409E, 0x7DCA389E, 0x7DCB409E, 0x7DCC389E, 0x7DCD409E, 0x7DCE389E, - 0x7DCF409E, 0x7DD1389E, 0x7DD2409E, 0x7DD4389E, 0x7DD5409E, 0x7DD6389E, 0x7DD7409E, 0x7DD90078, - 0x7DEA209E, 0x7DEB489E, 0x7DEC209E, 0x7DEF409E, 0x7DF3389E, 0x7DF5409E, 0x7DFC389E, 0x7DFD209E, - 0x7DFE409E, 0x7DFF389E, 0x7E00409E, 0x7E32209E, 0x7E4C389E, 0x7E70489E, 0x7E7B409E, 0x7E89209E, - 0x7E97389E, 0x7E9A489E, 0x7E9E209E, 0x7E9F00B4, 0x7EA00078, 0x7EA8389E, 0x7EAC209E, 0x7EAE389E, - 0x7EAF209E, 0x7EB0389E, 0x7EB1209E, 0x7EB4389E, 0x7EB5209E, 0x7EB8389E, 0x7EBA209E, 0x7EC3389E, - 0x7EC80078, 0x7EC9389E, 0x7ECB209E, 0x7ECC389E, 0x7ECD209E, 0x7EDA389E, 0x7EDB209E, 0x7EDC389E, - 0x7EDE209E, 0x7EE2389E, 0x7EE3209E, 0x7EE40078, 0x7EF8409E, 0x7EFE4140, 0x7EFF0078, 0x7F000083, - 0x7F088006, 0x7F0C80BF, 0x7F0D0078, 0x7F100083, 0x7F120078, 0x7F188006, 0x7F198099, 0x7F1A8038, - 0x7F1B80BF, 0x7F230006, 0x7F2480BF, 0x7F251006, 0x7F271038, 0x7F28600C, 0x7F2A6006, 0x7F2C6099, - 0x7F2D60BF, 0x7F306006, 0x7F31600B, 0x7F326019, 0x7F346006, 0x7F356007, 0x7F360078, 0x7F38409E, - 0x7F41209E, 0x7F46489E, 0x7F47209E, 0x7F49489E, 0x7F4A209E, 0x7F4C489E, 0x7F4D209E, 0x7F4E489E, - 0x7F4F209E, 0x7F50489E, 0x7F51209E, 0x7F52489E, 0x7F53209E, 0x7F54489E, 0x7F55209E, 0x7F5A489E, - 0x7F5B209E, 0x7F5C489E, 0x7F5D209E, 0x7F5E489E, 0x7F5F209E, 0x7F60489E, 0x7F61209E, 0x7F62489E, - 0x7F63209E, 0x7F64489E, 0x7F65209E, 0x7F66489E, 0x7F67209E, 0x7F68489E, 0x7F69209E, 0x7F6A489E, - 0x7F6B209E, 0x7F6C489E, 0x7F6D209E, 0x7F6E489E, 0x7F6F209E, 0x7F70489E, 0x7F71209E, 0x7F72489E, - 0x7F73209E, 0x7F74489E, 0x7F75209E, 0x7F76489E, 0x7F77209E, 0x7F7A489E, 0x7F7B209E, 0x7F7F0078, - 0x7F818806, 0x7F828808, 0x7F838806, 0x7F848809, 0x7F858806, 0x7F86880C, 0x7F88880E, 0x7F898810, - 0x7F8A8812, 0x7F8B8814, 0x7F8C8816, 0x7F8D880C, 0x7F8E8818, 0x7F8F881A, 0x7F908806, 0x7F918860, - 0x7F9E8806, 0x7F9F8837, 0x7FA18861, 0x7FAE8819, 0x7FB0880A, 0x7FB15009, 0x7FB25006, 0x7FB35071, - 0x7FB85081, 0x7FB95071, 0x7FCF5081, 0x7FD05071, 0x7FE00078, 0x7FE15071, 0x7FE40078, 0x7FE55071, - 0x7FE80078, 0x7FE95071, 0x7FEC0078, 0x7FED5071, 0x7FEF0078, 0x7FF08808, 0x7FF18819, 0x7FF28854, - 0x7FF38808, 0x7FF45054, 0x7FF55019, 0x7FF75054, 0x7FF80078, 0x7FFD0141, 0x7FFE0054, 0x7FFF0078, - 0x80000071, 0x80060078, 0x80070071, 0x801F0078, 0x80200071, 0x80270078, 0x80280071, 0x802F0078, - 0x80400071, 0x807E0078, 0x80800097, 0x80810094, 0x80820078, 0x808400B6, 0x808500B7, 0x808600B8, - 0x808700B9, 0x808800B0, 0x808900BA, 0x808A00BB, 0x808B00BC, 0x808C00BD, 0x808D0142, 0x808E0143, - 0x808F0144, 0x80900145, 0x809100B1, 0x80920146, 0x80930147, 0x80940148, 0x80950149, 0x8096014A, - 0x8097014B, 0x8098014C, 0x8099014D, 0x809A0078, 0x809C0094, 0x80A0014E, 0x80A1014F, 0x80A20150, - 0x80A30151, 0x80A40152, 0x80A50150, 0x80A60153, 0x80A70151, 0x80A80154, 0x80A90155, 0x80AA0156, - 0x80AB0157, 0x80AC014F, 0x80AE0158, 0x80B00154, 0x80B30150, 0x80B50155, 0x80B60153, 0x80B90151, - 0x80BA0150, 0x80BB005F, 0x80BD0054, 0x80C500C3, 0x80C60078, 0x81800071, 0x819000AD, 0x819100B0, - 0x81920078, 0x81980071, 0x81A50159, 0x81A60078, 0x81C00071, 0x81CF0078, 0x81D00071, 0x81E20078, - 0x81E40071, 0x81E80094, 0x81E90158, 0x81EA015A, 0x81EB0078, 0x8200015B, 0x8214015C, 0x82280071, - 0x824F0078, 0x825000A8, 0x825100A9, 0x825200AA, 0x825300AB, 0x825400AC, 0x82550078, 0x8400009B, - 0x84030078, 0x8404009B, 0x841B0078, 0x841C009B, 0x841D0078, 0x841E009B, 0x841F0078, 0x8500009B, - 0x85010083, 0x85020078, 0x85030083, 0x85040078, 0x85060083, 0x8508009B, 0x850A0078, 0x850B009B, - 0x850C0078, 0x850D009B, 0x851A0078, 0x851C0083, 0x851E0078, 0x8520015D, 0x8521015E, 0x8522015F, - 0x85230160, 0x85240078, 0x8528009A, 0x852D0078, 0xE8000094, 0xE87B0078, 0xE8800094, 0xE8940078, - 0xE8950094, 0xE8AF0894, 0xE8B300A7, 0xE8B40083, 0xE8B50094, 0xE8B700A7, 0xE8BA0057, 0xE8BE0083, - 0xE8C20094, 0xE8C30083, 0xE8C60094, 0xE8D50083, 0xE8D70094, 0xE8DE0894, 0xE8E10094, 0xE8EF0078, - 0xE9000054, 0xE9210083, 0xE9230078, 0xE9800054, 0xE9AC0078, 0xEA002877, 0xEA0D2855, 0xEA1A2877, - 0xEA272855, 0xEA342877, 0xEA412855, 0xEA4E2877, 0xEA500078, 0xEA512877, 0xEA520078, 0xEA532877, - 0xEA540078, 0xEA552877, 0xEA5B2855, 0xEA5D0078, 0xEA5F2855, 0xEA620078, 0xEA632855, 0xEA682877, - 0xEA752855, 0xEA822877, 0xEA830078, 0xEA842877, 0xEA860078, 0xEA872877, 0xEA8F2855, 0xEA9C2877, - 0xEA9D0078, 0xEA9E2877, 0xEAA40078, 0xEAA52877, 0xEAA92855, 0xEAB62877, 0xEAC32855, 0xEAD02877, - 0xEADD2855, 0xEAEA2877, 0xEAF72855, 0xEB042877, 0xEB112855, 0xEB1E2877, 0xEB2B2855, 0xEB382877, - 0xEB452855, 0xEB530078, 0xEB542877, 0xEB612855, 0xEB712877, 0xEB7E2855, 0xEB8E2877, 0xEB9B2855, - 0xEBAB2877, 0xEBB82855, 0xEBC82877, 0xEBD52855, 0xEBE50078, 0xEBE7280E, 0xEBE82810, 0xEBE92812, - 0xEBEA2814, 0xEBEB2816, 0xEBEC280E, 0xEBED2810, 0xEBEE2812, 0xEBEF2814, 0xEBF02816, 0xEBF1280E, - 0xEBF22810, 0xEBF32812, 0xEBF42814, 0xEBF52816, 0xEBF6280E, 0xEBF72810, 0xEBF82812, 0xEBF92814, - 0xEBFA2816, 0xEBFB280E, 0xEBFC2810, 0xEBFD2812, 0xEBFE2814, 0xEBFF2816, 0xEC000078 - }; - - static const uint32_t a1[] = { - 0x00000071, 0x536C0078, 0x7C000871, 0x7D0F0078 - }; - - static const uint32_t a7[] = { - 0x00100057, 0x00400078, 0x00800083, 0x00F80078, 0x8000013F, 0xFFFF0078 - }; - - static const uint32_t a8[] = { - 0x0000013F, 0x7FFF0078 - }; - - static const uint32_t a16[] = { - 0x00800865, 0x00880065, 0x00890865, 0x00930065, 0x00940865, 0x00980161, 0x00991065, 0x009A0865, - 0x009C0863, 0x009F1063, 0x00A00063, 0x00A10863, 0x00A41055, 0x00A50065, 0x00A60865, 0x00A90065, - 0x00AA0865, 0x00B30065, 0x00B40865, 0x00BC0863, 0x00BF1162, 0x00C00163, 0x00C10065, 0x00C30063, - 0x00C40068, 0x00C50063, 0x00C60055, 0x00C70164, 0x00C80063, 0x00C90068, 0x00CA0165, 0x00CB0166, - 0x00CC0065, 0x00CD0055, 0x00CE0167, 0x00CF0168, 0x00D00865, 0x00D10065, 0x00D30063, 0x00D4006F, - 0x00D50055, 0x00D60065, 0x00D70863, 0x00D80070, 0x00D90063, 0x00DB0169, 0x00DC0065, 0x00DD0071, - 0x00DE0065, 0x00DF016A, 0x00E00071, 0x00E21074, 0x00E31072, 0x00E41073, 0x00E51074, 0x00E60863, - 0x00EE016B, 0x00EF0865, 0x00F20065, 0x00F30865, 0x00F81072, 0x00F91073, 0x00FA0865, 0x00FB016C, - 0x00FC0865, 0x010E0065, 0x010F0865, 0x01100055, 0x01110065, 0x01130865, 0x011A0055, 0x011D0063, - 0x011E016D, 0x011F0055, 0x0120016E, 0x01210078, 0x01280055, 0x0129016F, 0x012A0055, 0x012B007A, - 0x012C0170, 0x012D0171, 0x012E0055, 0x01310172, 0x01320055, 0x01340173, 0x01350055, 0x01370173, - 0x01380055, 0x013A0174, 0x013B0055, 0x0141007D, 0x01420055, 0x0145007E, 0x01460055, 0x01587881, - 0x015C0082, 0x015D0081, 0x01610037, 0x01630082, 0x01680081, 0x01690037, 0x016C1037, 0x016F0037, - 0x01707881, 0x01720037, 0x01800083, 0x01A00883, 0x01A20175, 0x01A30083, 0x01B80078, 0x01BA0037, - 0x01BB0078, 0x01C20837, 0x01C30806, 0x01C40885, 0x01C50078, 0x01C70887, 0x01C80060, 0x01D50860, - 0x01D60889, 0x01D80061, 0x01E50861, 0x01E6088C, 0x01E70078, 0x01E81176, 0x01E90877, 0x01EA1177, - 0x01EB0055, 0x01EC0065, 0x01F81093, 0x01F90055, 0x01FA1178, 0x01FB0063, 0x01FC10D8, 0x01FD0065, - 0x01FE0077, 0x02000892, 0x02020092, 0x02030892, 0x02040092, 0x02060892, 0x02070092, 0x02080060, - 0x020C0860, 0x020D0060, 0x02180061, 0x021C0861, 0x021D0061, 0x02280893, 0x022A0093, 0x022B0893, - 0x022C0093, 0x022E0893, 0x022F0093, 0x02300065, 0x023B0865, 0x023C0065, 0x02410083, 0x02430078, - 0x02440095, 0x02450065, 0x02600863, 0x02610063, 0x02670078, 0x02680865, 0x026A0065, 0x026B0865, - 0x026C0065, 0x026D0865, 0x02700065, 0x02710865, 0x02740065, 0x02750865, 0x027B0065, 0x027C0865, - 0x027D0078, 0x02800065, 0x02880078, 0x02980096, 0x02AB0078, 0x02AC0081, 0x02AD0097, 0x02B00098, - 0x02C31055, 0x02C40097, 0x02C50078, 0x02C80083, 0x02E1009A, 0x02E20083, 0x02E40078, 0x02E8009B, - 0x02F50078, 0x02F8009B, 0x02F9009A, 0x02FA0078, 0x0300009C, 0x03020078, 0x03050140, 0x0306009D, - 0x03070054, 0x03080083, 0x030B0078, 0x030D009D, 0x030E0078, 0x030F009D, 0x0310009E, 0x0311089E, - 0x0313009E, 0x031D0078, 0x0320009E, 0x03250083, 0x032F0078, 0x03300179, 0x0331017A, 0x0332017B, - 0x0333017C, 0x0334017D, 0x033500A5, 0x0336009D, 0x0337009E, 0x033A109E, 0x033C009E, 0x0369089E, - 0x036A009E, 0x036B0083, 0x036E009C, 0x036F0083, 0x0372009F, 0x03730083, 0x03740054, 0x03750083, - 0x0377009E, 0x0378000F, 0x03790011, 0x037A0013, 0x037B0015, 0x037C0017, 0x037D009E, 0x037E00A6, - 0x037F009E, 0x0380009D, 0x03870057, 0x03880083, 0x0389009E, 0x03980083, 0x03A50078, 0x03A6009E, - 0x03B70078, 0x03C0009E, 0x03D30083, 0x03D8009E, 0x03D90078, 0x04800083, 0x048100A7, 0x04820071, - 0x04940871, 0x04950071, 0x04980871, 0x04990071, 0x049D0078, 0x049E0071, 0x049F00A7, 0x04A00083, - 0x04A400A7, 0x04A60083, 0x04A70078, 0x04A80083, 0x04AA0078, 0x04AC0871, 0x04B00071, 0x04B10083, - 0x04B20097, 0x04B3017E, 0x04B4017F, 0x04B50180, 0x04B60181, 0x04B70182, 0x04B80078, 0x04BE0071, - 0x04BF0078, 0x04C00083, 0x04C100A7, 0x04C20071, 0x04C60078, 0x04C70071, 0x04C80078, 0x04C90071, - 0x04D40078, 0x04D50071, 0x04D80078, 0x04DB0071, 0x04DD0078, 0x04DE0071, 0x04DF00A7, 0x04E00083, - 0x04E20078, 0x04E300A7, 0x04E40078, 0x04E508A7, 0x04E60083, 0x04E70078, 0x04EB00A7, 0x04EC0078, - 0x04EE0871, 0x04F00071, 0x04F10083, 0x04F20078, 0x04F3017E, 0x04F4017F, 0x04F50180, 0x04F60181, - 0x04F70182, 0x04F80071, 0x04F90008, 0x04FA00B6, 0x04FB00B7, 0x04FC0183, 0x04FD0078, 0x05000083, - 0x050100A7, 0x05020071, 0x05050078, 0x05070071, 0x05080078, 0x05090071, 0x05140078, 0x05150071, - 0x05180078, 0x05190871, 0x051A0071, 0x051B0078, 0x051C0071, 0x051D0078, 0x051F00A7, 0x05200083, - 0x05210078, 0x05230083, 0x05240078, 0x05250083, 0x05270078, 0x052C0871, 0x052E0078, 0x0533017E, - 0x0534017F, 0x05350180, 0x05360181, 0x05370182, 0x05380083, 0x05390071, 0x053A0078, 0x05400083, - 0x054100A7, 0x05420071, 0x05540078, 0x05550071, 0x05580078, 0x05590071, 0x055D0078, 0x055E0071, - 0x055F00A7, 0x05600083, 0x056400A7, 0x05660083, 0x05670078, 0x05700071, 0x05710083, 0x05720078, - 0x0573017E, 0x0574017F, 0x05750180, 0x05760181, 0x05770182, 0x05780008, 0x05790078, 0x05800083, - 0x058100A7, 0x05820071, 0x05860078, 0x05870071, 0x05880078, 0x05890071, 0x05940078, 0x05950071, - 0x05980078, 0x05990071, 0x059D0078, 0x059E0071, 0x059F0083, 0x05A20078, 0x05A300A7, 0x05A40078, - 0x05A508A7, 0x05A60083, 0x05A70078, 0x05AB00A7, 0x05AC0078, 0x05AE0871, 0x05AF0071, 0x05B10078, - 0x05B3017E, 0x05B4017F, 0x05B50180, 0x05B60181, 0x05B70182, 0x05B80071, 0x05B90078, 0x05C10071, - 0x05C50078, 0x05C70071, 0x05C80078, 0x05C90071, 0x05CB0078, 0x05CC0071, 0x05CD0078, 0x05CF0071, - 0x05D00078, 0x05D10071, 0x05D20078, 0x05D40071, 0x05D50078, 0x05D70071, 0x05DD0078, 0x05DF00A7, - 0x05E10078, 0x05E300A7, 0x05E40078, 0x05E508A7, 0x05E60083, 0x05E70078, 0x05EB00A7, 0x05EC0078, - 0x05F3017E, 0x05F4017F, 0x05F50180, 0x05F60181, 0x05F70182, 0x05F80184, 0x05F90054, 0x05FC0008, - 0x05FD0078, 0x060000A7, 0x06020071, 0x06060078, 0x06070071, 0x06080078, 0x06090071, 0x06140078, - 0x06150071, 0x061D0078, 0x061F0083, 0x062000A7, 0x06220078, 0x06230083, 0x06240078, 0x06250083, - 0x06270078, 0x062A0083, 0x062B0078, 0x06300071, 0x06310078, 0x0633017E, 0x0634017F, 0x06350180, - 0x06360181, 0x06370182, 0x06380078, 0x064100A7, 0x06420071, 0x06460078, 0x06470071, 0x06480078, - 0x06490071, 0x06540078, 0x06550071, 0x065D0078, 0x065E0071, 0x065F00B2, 0x066000A7, 0x06620078, - 0x066308A7, 0x06640078, 0x066508A7, 0x06660083, 0x06670078, 0x066A00A7, 0x066B0078, 0x06700071, - 0x06710078, 0x0673017E, 0x0674017F, 0x06750180, 0x06760181, 0x06770182, 0x06780078, 0x068100A7, - 0x06820071, 0x06860078, 0x06870071, 0x06880078, 0x06890071, 0x06940078, 0x06950071, 0x069D0078, - 0x069F00A7, 0x06A00083, 0x06A20078, 0x06A300A7, 0x06A40078, 0x06A508A7, 0x06A60083, 0x06A70078, - 0x06AB00A7, 0x06AC0078, 0x06B00071, 0x06B10078, 0x06B3017E, 0x06B4017F, 0x06B50180, 0x06B60181, - 0x06B70182, 0x06B80078, 0x06C100A7, 0x06C20071, 0x06CB0078, 0x06CD0071, 0x06DF0078, 0x06E00071, - 0x06E30078, 0x06E700A7, 0x06E90083, 0x06EA0078, 0x06EC00A7, 0x06EE08A7, 0x06EF00A7, 0x06F00078, - 0x06F900A7, 0x06FA0078, 0x07000071, 0x07180083, 0x07191071, 0x071A0083, 0x071D0078, 0x071F0008, - 0x07200071, 0x07230083, 0x07270097, 0x0728017E, 0x0729017F, 0x072A0180, 0x072B0181, 0x072C0182, - 0x072D0097, 0x072E0078, 0x07400071, 0x07410078, 0x07430071, 0x07440078, 0x07460071, 0x07470078, - 0x074A0071, 0x07540078, 0x07550071, 0x07580083, 0x07591071, 0x075A0083, 0x075E0071, 0x075F0078, - 0x07600071, 0x07620078, 0x07640083, 0x07670078, 0x0768017E, 0x0769017F, 0x076A0180, 0x076B0181, - 0x076C0182, 0x076D0078, 0x076E1071, 0x076F0078, 0x07800094, 0x07820097, 0x07890094, 0x078C0083, - 0x078D0094, 0x0790017E, 0x0791017F, 0x07920180, 0x07930181, 0x07940182, 0x079500B3, 0x079A0083, - 0x079D00BF, 0x079F00A7, 0x07A00071, 0x07A10871, 0x07A20071, 0x07A60871, 0x07A70071, 0x07AB0871, - 0x07AC0071, 0x07B40871, 0x07B50078, 0x07B80083, 0x07B90883, 0x07BB1083, 0x07BD0083, 0x07BF00A7, - 0x07C00883, 0x07C10083, 0x07C20097, 0x07C30083, 0x07C40071, 0x07C60078, 0x07C80083, 0x07C90883, - 0x07CA0083, 0x07CE0883, 0x07CF0083, 0x07D30883, 0x07D40083, 0x07DC0883, 0x07DD0083, 0x07DE0078, - 0x07DF0094, 0x07E60078, 0x07E70094, 0x07E80097, 0x07E90078, 0x08000071, 0x08150078, 0x08160083, - 0x081800A7, 0x08190078, 0x081B0083, 0x081D0078, 0x0820017E, 0x0821017F, 0x08220180, 0x08230181, - 0x08240182, 0x08250097, 0x08280071, 0x082B00A7, 0x082C0083, 0x082D0078, 0x085000B5, 0x08630078, - 0x08680071, 0x087D0097, 0x087E0078, 0x08800071, 0x08AD0078, 0x08AF0071, 0x08D10078, 0x08D40071, - 0x08FD0078, 0x09000071, 0x09240078, 0x09250071, 0x09270078, 0x09280071, 0x092B0078, 0x092D0071, - 0x092F0078, 0x09300071, 0x09440078, 0x09450071, 0x09470078, 0x09480071, 0x09580078, 0x09590071, - 0x095B0078, 0x095C0071, 0x095F0078, 0x09610071, 0x09630078, 0x09640071, 0x096B0078, 0x096C0071, - 0x09880078, 0x09890071, 0x098B0078, 0x098C0071, 0x09AD0078, 0x09AF0083, 0x09B00097, 0x09B400AD, - 0x09B500AE, 0x09B6012D, 0x09B7012E, 0x09B8012F, 0x09B90185, 0x09BA0186, 0x09BB0187, 0x09BC0188, - 0x09BD0184, 0x09BE0078, 0x09C00071, 0x09C80054, 0x09CD0078, 0x09D00071, 0x09FA0078, 0x0A000071, - 0x0B360097, 0x0B370071, 0x0B3B0078, 0x0B400071, 0x0B4D00B4, 0x0B4E0078, 0x0B500071, 0x0B750097, - 0x0B770189, 0x0B780078, 0x0B800071, 0x0B860078, 0x0B870071, 0x0B890083, 0x0B8A0078, 0x0B900071, - 0x0B990083, 0x0B9A0097, 0x0B9B0078, 0x0BA00071, 0x0BA90083, 0x0BAA0078, 0x0BB00071, 0x0BB60078, - 0x0BB70071, 0x0BB80078, 0x0BB90083, 0x0BBA0078, 0x0BC00071, 0x0BDA00C2, 0x0BDB0083, 0x0BDF00A7, - 0x0BE40083, 0x0BEA0097, 0x0BEB0081, 0x0BEC0097, 0x0BED0008, 0x0BEE0083, 0x0BEF0078, 0x0BF0017E, - 0x0BF1017F, 0x0BF20180, 0x0BF30181, 0x0BF40182, 0x0BF50078, 0x0BF80106, 0x0BF90107, 0x0BFA0108, - 0x0BFB0109, 0x0BFC010A, 0x0BFD0078, 0x0C000006, 0x0C050083, 0x0C070078, 0x0C08017E, 0x0C09017F, - 0x0C0A0180, 0x0C0B0181, 0x0C0C0182, 0x0C0D0078, 0x0C100071, 0x0C210081, 0x0C220071, 0x0C3C0078, - 0x0C400071, 0x0C540083, 0x0C550078, 0x0C800071, 0x0C8E0078, 0x0C900083, 0x0C9100A7, 0x0C930083, - 0x0C9400C8, 0x0C960078, 0x0C9800A7, 0x0C9C0083, 0x0C9E0078, 0x0CA20006, 0x0CA3017E, 0x0CA4017F, - 0x0CA50180, 0x0CA60181, 0x0CA70182, 0x0CA80071, 0x0CB70078, 0x0CB80071, 0x0CBA0078, 0x0CC00071, - 0x0CD50078, 0x0CD800A7, 0x0CE00071, 0x0CE400A7, 0x0CE50078, 0x0CE8017E, 0x0CE9017F, 0x0CEA0180, - 0x0CEB0181, 0x0CEC0182, 0x0CED0078, 0x0CEF0006, 0x0CF00054, 0x0D000071, 0x0D0B0083, 0x0D0C00A7, - 0x0D0E0078, 0x0D0F0097, 0x0D100078, 0x0E800055, 0x0E967881, 0x0E970081, 0x0E987881, 0x0E9D0081, - 0x0E9E7881, 0x0EB17055, 0x0EB50055, 0x0ECD7881, 0x0EE00083, 0x0EE20078, 0x0F000865, 0x0F4B0855, - 0x0F4D098A, 0x0F4E0078, 0x0F500865, 0x0F7D0078, 0x0F8008C9, 0x0F8408CA, 0x0F8808C9, 0x0F8B0078, - 0x0F8C08CA, 0x0F8F0078, 0x0F9008C9, 0x0F9408CA, 0x0F9808C9, 0x0F9C08CA, 0x0FA008C9, 0x0FA30078, - 0x0FA408CA, 0x0FA70078, 0x0FA808C9, 0x0FAC08CA, 0x0FB008C9, 0x0FB408CA, 0x0FB808CB, 0x0FB908CC, - 0x0FBB08CD, 0x0FBC08CE, 0x0FBD08CF, 0x0FBE08D0, 0x0FBF0078, 0x0FC008C9, 0x0FC408D1, 0x0FC808C9, - 0x0FCC08D1, 0x0FD008C9, 0x0FD408D1, 0x0FD808C9, 0x0FD9098B, 0x0FDA0078, 0x0FDB0855, 0x0FDC08CA, - 0x0FDD08D2, 0x0FDE1037, 0x0FE00837, 0x0FE1098B, 0x0FE20078, 0x0FE30855, 0x0FE408D5, 0x0FE60837, - 0x0FE808C9, 0x0FE90855, 0x0FEA0078, 0x0FEB0855, 0x0FEC08CA, 0x0FED08D6, 0x0FEE0837, 0x0FF008C9, - 0x0FF10855, 0x0FF20890, 0x0FF30855, 0x0FF408CA, 0x0FF508D7, 0x0FF60837, 0x0FF80078, 0x0FF9098B, - 0x0FFA0078, 0x0FFB0855, 0x0FFC08D9, 0x0FFD08DA, 0x0FFE0837, 0x0FFF0078, 0x10000805, 0x10011005, - 0x10035805, 0x10041005, 0x10050057, 0x1007018C, 0x10085899, 0x10090099, 0x100B1006, 0x100C018D, - 0x100D00DB, 0x100E018D, 0x100F00DB, 0x10100006, 0x10121006, 0x10130006, 0x1014018E, 0x1015018F, - 0x10160190, 0x10175853, 0x10180007, 0x10191007, 0x101A0006, 0x101B1006, 0x101C0126, 0x101D0006, - 0x101F0038, 0x10200006, 0x10220009, 0x10231006, 0x10250006, 0x102B1006, 0x102C0006, 0x102F1005, - 0x10300057, 0x10320078, 0x10350057, 0x10387855, 0x10390078, 0x103A7910, 0x103B7911, 0x103C7912, - 0x103D780B, 0x103E7809, 0x103F7855, 0x1040705D, 0x1041705B, 0x10427110, 0x10437111, 0x10447112, - 0x1045700B, 0x10467009, 0x10470078, 0x10487081, 0x104A0078, 0x10500008, 0x105B0078, 0x10680083, - 0x106E0095, 0x10700083, 0x10710095, 0x10720083, 0x10760078, 0x10801054, 0x10831077, 0x10841054, - 0x10852877, 0x10872855, 0x10882877, 0x10892855, 0x108A2877, 0x108B0054, 0x108C2877, 0x108F0054, - 0x10901054, 0x10910054, 0x10950991, 0x10962877, 0x10972855, 0x10982877, 0x109A1071, 0x109C2855, - 0x109D1054, 0x109E2855, 0x109F2877, 0x10A00019, 0x10A22877, 0x10A32855, 0x10A50019, 0x10A60078, - 0x10A9305F, 0x10AF3106, 0x10B01192, 0x10B11193, 0x10B21194, 0x10B31195, 0x10B41196, 0x10B51197, - 0x10B61198, 0x10B71199, 0x10B8119A, 0x10B9119B, 0x10BA119C, 0x10BB119D, 0x10BC119E, 0x10BD119F, - 0x10BE11A0, 0x10BF11A1, 0x10C001A2, 0x10C101A3, 0x10C20078, 0x10C80019, 0x10CA0054, 0x10CD0819, - 0x10CE0054, 0x10D10019, 0x10D20054, 0x10E60854, 0x10E70819, 0x10E80054, 0x10FA0019, 0x110000E8, - 0x11020019, 0x110408FB, 0x110500FC, 0x11070019, 0x110800E8, 0x11090059, 0x110A01A4, 0x110B0019, - 0x110D00E8, 0x11110019, 0x111500E8, 0x111610E8, 0x111800E8, 0x111A0019, 0x111C00E8, 0x111E00FE, - 0x111F00E8, 0x112008E8, 0x112101A5, 0x112200E8, 0x112308E8, 0x112500E8, 0x11260019, 0x112900FE, - 0x112B0019, 0x112F00E8, 0x11300019, 0x113200FE, 0x11360819, 0x113708FE, 0x113900FE, 0x113A08FE, - 0x113B00FE, 0x113C08FE, 0x113D00FE, 0x114008FE, 0x114100FE, 0x114208FE, 0x114300FE, 0x114408FE, - 0x114500FE, 0x11460019, 0x114700FD, 0x11490019, 0x115100FE, 0x11520019, 0x115300E8, 0x115401A6, - 0x115608E8, 0x115800FE, 0x115C0019, 0x115F00E8, 0x11600019, 0x116400FD, 0x116601A7, 0x11670019, - 0x116800FE, 0x11690019, 0x116B00FE, 0x117008FE, 0x117200FE, 0x117508FE, 0x11770019, 0x117800FE, - 0x11790102, 0x117A00E8, 0x117B0103, 0x117C00E8, 0x117D0104, 0x117E0105, 0x117F00E8, 0x11800054, - 0x118400FE, 0x11860054, 0x119000E8, 0x11910054, 0x11940809, 0x11950054, 0x119B0094, 0x11BD0054, - 0x11CA0094, 0x11CB0054, 0x11CD0019, 0x11DA00BF, 0x11DB0054, 0x11EE0078, 0x12000054, 0x12130078, - 0x12200054, 0x12250078, 0x123018C4, 0x123118C5, 0x123218C6, 0x123318C7, 0x1234191F, 0x1235191A, - 0x1236191B, 0x1237191C, 0x1238191D, 0x1239191E, 0x123A10C4, 0x123B10C5, 0x123C10C6, 0x123D10C7, - 0x123E111F, 0x123F111A, 0x1240111B, 0x1241111C, 0x1242111D, 0x1243111E, 0x1244105A, 0x124510E3, - 0x124610E4, 0x124710E5, 0x124811A8, 0x124911A9, 0x124A11AA, 0x124B11AB, 0x124C11AC, 0x124D11AD, - 0x124E1094, 0x125B1918, 0x12681919, 0x1275010B, 0x1276010C, 0x1277010D, 0x1278010E, 0x1279010F, - 0x127A0106, 0x127B0107, 0x127C0108, 0x127D0109, 0x127E010A, 0x127F00C3, 0x12800054, 0x12DB0019, - 0x12DC0054, 0x12E00019, 0x12E10054, 0x12FC0019, 0x13000054, 0x13370019, 0x13380054, 0x134E0078, - 0x13500054, 0x13590078, 0x13800054, 0x13820078, 0x13830054, 0x13850078, 0x13860054, 0x13A90078, - 0x13AC0054, 0x13AF0078, 0x13B00054, 0x13B4000A, 0x13BB00C4, 0x13BC00C5, 0x13BD00C6, 0x13BE00C7, - 0x13BF011F, 0x13C000C4, 0x13C100C5, 0x13C200C6, 0x13C300C7, 0x13C4011F, 0x13C500C4, 0x13C600C5, - 0x13C700C6, 0x13C800C7, 0x13C9011F, 0x13CA0078, 0x13CC0054, 0x13DF0078, 0x13E00019, 0x13E100FD, - 0x13E20009, 0x13E30078, 0x13E80019, 0x13E900E8, 0x13EA00FD, 0x13EB0019, 0x13EE00FD, 0x13EF0019, - 0x13F100FE, 0x13F3000A, 0x13F60078, 0x13F80019, 0x14000094, 0x14800019, 0x14C10009, 0x14C601AE, - 0x14C701AF, 0x14C80009, 0x14CC0019, 0x14CD00E8, 0x14D80019, 0x14E000FE, 0x14E100E8, 0x14E200FE, - 0x14E30019, 0x14E400E8, 0x14E50019, 0x14E700FD, 0x14E90019, 0x14EA00FE, 0x14EB0019, 0x14EC000A, - 0x14EE0019, 0x14F000E8, 0x14F30019, 0x14F400E8, 0x14F50019, 0x14FA01B0, 0x14FB00E8, 0x14FC00FE, - 0x14FD0019, 0x14FE000A, 0x14FF0019, 0x150500E8, 0x150E0019, 0x150F00E8, 0x15110019, 0x151400E8, - 0x151500FD, 0x15170019, 0x151A00FE, 0x151B0019, 0x151E00FE, 0x151F0019, 0x152B00E8, 0x152C0019, - 0x153200FE, 0x15330019, 0x153500E8, 0x15380019, 0x153900E8, 0x153A1019, 0x153B0019, 0x153C00FD, - 0x153D00E8, 0x153E00FD, 0x154200E8, 0x154500FD, 0x154600E8, 0x154800FD, 0x154E00E8, 0x155000FD, - 0x155100E8, 0x15520019, 0x155300FE, 0x155700FD, 0x155800E8, 0x155900FD, 0x155A00E8, 0x155D00FD, - 0x156300E8, 0x156600FD, 0x156B0019, 0x157101B1, 0x15730019, 0x157600FE, 0x15770019, 0x157900E8, - 0x157A0019, 0x157B00FD, 0x157D00E8, 0x157F0019, 0x15800054, 0x158A0078, 0x16000096, 0x16170078, - 0x16180098, 0x162F0078, 0x16400065, 0x16720054, 0x16750078, 0x167C0006, 0x167E005F, 0x167F0006, - 0x16800125, 0x16930078, 0x16980071, 0x16B30078, 0x16B77881, 0x16B80078, 0x16C00071, 0x16CB0078, - 0x16D00071, 0x16D30078, 0x16D40071, 0x16D70078, 0x16D80071, 0x16DB0078, 0x16DC0071, 0x16DF0078, - 0x16E00071, 0x16E30078, 0x16E40071, 0x16E70078, 0x16E80071, 0x16EB0078, 0x16EC0071, 0x16EF0078, - 0x17000006, 0x170100E0, 0x17030006, 0x17040126, 0x17050006, 0x170600E0, 0x17070006, 0x170B0099, - 0x170C0078, 0x170E00E0, 0x170F0078, 0x17400054, 0x174F1054, 0x17500054, 0x17791054, 0x177A0078, - 0x17801054, 0x17EB0078, 0x17F80054, 0x17FE0078, 0x18000006, 0x18020081, 0x180301B2, 0x1804000A, - 0x18090054, 0x180A000A, 0x180E00B4, 0x180F00BF, 0x181001B3, 0x181101B4, 0x181201B5, 0x181301B6, - 0x181401B7, 0x18150083, 0x18180081, 0x181B0054, 0x181C11B8, 0x181D0081, 0x181E0006, 0x181F0054, - 0x18200071, 0x18320871, 0x18350071, 0x18380871, 0x183A0071, 0x183B0871, 0x183D0071, 0x183E0871, - 0x183F0071, 0x184B0078, 0x184C0083, 0x184D1037, 0x184E0081, 0x184F8071, 0x18500071, 0x18620871, - 0x18650071, 0x18680871, 0x186A0071, 0x186B0871, 0x186D0071, 0x186E0871, 0x186F0071, 0x187B0871, - 0x187D0006, 0x187E0081, 0x187F8071, 0x18800078, 0x18820071, 0x18960078, 0x18981071, 0x18C70078, - 0x18C80094, 0x18C978B6, 0x18CA78B7, 0x18CB7894, 0x18D00071, 0x18DC0078, 0x18E00054, 0x18E80078, - 0x18F80071, 0x19001094, 0x190E1054, 0x190F0078, 0x191010B6, 0x191110B7, 0x191210B8, 0x191310B9, - 0x191410B0, 0x19151094, 0x19220078, 0x192819B9, 0x192919BA, 0x192A19BB, 0x192B19BC, 0x192C19BD, - 0x192D19BE, 0x192E19BF, 0x192F19C0, 0x19301894, 0x193E1854, 0x193F0094, 0x194018B6, 0x194118B7, - 0x194218B8, 0x194318B9, 0x194418B0, 0x19451894, 0x195819C1, 0x195919C2, 0x195A19C3, 0x195B19C4, - 0x195C19C5, 0x195D19C6, 0x195E19C7, 0x195F19C8, 0x19601094, 0x19666854, 0x19681894, 0x197F0078, - 0x19806894, 0x19AC1094, 0x19B86894, 0x19BB6854, 0x19BD6894, 0x19EF6854, 0x19F01094, 0x19FF6854, - 0x1A000071, 0x26DB0078, 0x26E00054, 0x27000071, 0x4FDE0078, 0x50000071, 0x500A0081, 0x500B0071, - 0x52460078, 0x52480054, 0x52630078, 0x53800037, 0x538B0078, 0x54000071, 0x54050083, 0x54060071, - 0x541100A7, 0x54120083, 0x541300A7, 0x54140054, 0x54160078, 0x56000071, 0x6BD20078, 0x6C00013E, - 0x7000013F, 0x7C800871, 0x7D070071, 0x7D0A0871, 0x7D0F0071, 0x7D120871, 0x7D130071, 0x7D150871, - 0x7D170078, 0x7D180871, 0x7D350078, 0x7D380871, 0x7D6D0078, 0x7D801055, 0x7D830078, 0x7D891055, - 0x7D8C0078, 0x7D8E089B, 0x7D90289B, 0x7D94280B, 0x7D95089B, 0x7D9B0078, 0x7D9C089B, 0x7D9E0078, - 0x7DA0089B, 0x7DA20078, 0x7DA3089B, 0x7DA7109B, 0x7DA8209E, 0x7DAA489E, 0x7DAB209E, 0x7DAC489E, - 0x7DAD209E, 0x7DAE489E, 0x7DAF209E, 0x7DB0489E, 0x7DB1209E, 0x7DB2489E, 0x7DB3209E, 0x7DB4489E, - 0x7DB5209E, 0x7DB6489E, 0x7DB7209E, 0x7DB8489E, 0x7DB9209E, 0x7DBA489E, 0x7DBB209E, 0x7DBC489E, - 0x7DBD209E, 0x7DBE489E, 0x7DBF209E, 0x7DC0489E, 0x7DC1209E, 0x7DC8489E, 0x7DC9209E, 0x7DCA489E, - 0x7DCB209E, 0x7DCC489E, 0x7DCD209E, 0x7DCE489E, 0x7DCF209E, 0x7DD1489E, 0x7DD2209E, 0x7DD4489E, - 0x7DD5209E, 0x7DD6489E, 0x7DD7209E, 0x7DD90078, 0x7DE9409E, 0x7DEA389E, 0x7DEB409E, 0x7DEF209E, - 0x7DF3489E, 0x7DF5209E, 0x7DFC409E, 0x7DFD389E, 0x7DFE209E, 0x7DFF489E, 0x7E00409E, 0x7E32209E, - 0x7E4B389E, 0x7E6F489E, 0x7E7A409E, 0x7E88209E, 0x7E96389E, 0x7E9A489E, 0x7E9E409E, 0x7E9F00BF, - 0x7EA00078, 0x7EA8209E, 0x7EA9389E, 0x7EAD209E, 0x7EAE389E, 0x7EAF209E, 0x7EB0389E, 0x7EB3209E, - 0x7EB5389E, 0x7EB7209E, 0x7EB9389E, 0x7EBA209E, 0x7EBB389E, 0x7EBC209E, 0x7EBE389E, 0x7EBF209E, - 0x7EC1389E, 0x7EC2209E, 0x7EC4389E, 0x7EC5209E, 0x7EC6389E, 0x7EC80078, 0x7EC9389E, 0x7ECB209E, - 0x7ECE389E, 0x7ECF209E, 0x7EDA389E, 0x7EDB209E, 0x7EE1389E, 0x7EE3209E, 0x7EE40078, 0x7EF8409E, - 0x7EFE0054, 0x7EFF0078, 0x7F000083, 0x7F088006, 0x7F0B80B4, 0x7F0C8006, 0x7F0D0078, 0x7F100083, - 0x7F120078, 0x7F188099, 0x7F198038, 0x7F1A80B4, 0x7F220006, 0x7F2380B4, 0x7F241006, 0x7F261038, - 0x7F286006, 0x7F290078, 0x7F2A600C, 0x7F2B6006, 0x7F2C60B4, 0x7F2F6007, 0x7F306006, 0x7F31600D, - 0x7F326019, 0x7F330078, 0x7F346008, 0x7F356006, 0x7F360078, 0x7F38489E, 0x7F39009E, 0x7F3A0078, - 0x7F3B489E, 0x7F40409E, 0x7F45389E, 0x7F46409E, 0x7F48389E, 0x7F49409E, 0x7F4B389E, 0x7F4C409E, - 0x7F4D389E, 0x7F4E409E, 0x7F4F389E, 0x7F50409E, 0x7F51389E, 0x7F52409E, 0x7F53389E, 0x7F54409E, - 0x7F59389E, 0x7F5A409E, 0x7F5B389E, 0x7F5C409E, 0x7F5D389E, 0x7F5E409E, 0x7F5F389E, 0x7F60409E, - 0x7F61389E, 0x7F62409E, 0x7F63389E, 0x7F64409E, 0x7F65389E, 0x7F66409E, 0x7F67389E, 0x7F68409E, - 0x7F69389E, 0x7F6A409E, 0x7F6B389E, 0x7F6C409E, 0x7F6D389E, 0x7F6E409E, 0x7F6F389E, 0x7F70409E, - 0x7F71389E, 0x7F72409E, 0x7F73389E, 0x7F74409E, 0x7F75389E, 0x7F76409E, 0x7F79389E, 0x7F7A409E, - 0x7F7E0078, 0x7F7F0057, 0x7F808806, 0x7F818807, 0x7F838806, 0x7F84880A, 0x7F85880B, 0x7F86880D, - 0x7F87880C, 0x7F88880F, 0x7F898811, 0x7F8A8813, 0x7F8B8815, 0x7F8C8817, 0x7F8D8806, 0x7F8E8819, - 0x7F8F8806, 0x7F908860, 0x7F9D8835, 0x7F9E8836, 0x7F9F8838, 0x7FA08861, 0x7FAD8835, 0x7FAE8836, - 0x7FAF8809, 0x7FB05006, 0x7FB1500A, 0x7FB25006, 0x7FB35071, 0x7FCF5081, 0x7FD05071, 0x7FDF0078, - 0x7FE15071, 0x7FE40078, 0x7FE55071, 0x7FE80078, 0x7FE95071, 0x7FEC0078, 0x7FED5071, 0x7FEE0078, - 0x7FF08808, 0x7FF18837, 0x7FF28808, 0x7FF30078, 0x7FF45019, 0x7FF65054, 0x7FF70078, 0x7FFC0141, - 0x7FFE0054, 0x7FFF0078, 0x80000071, 0x80130078, 0x80140071, 0x801D0078, 0x801E0071, 0x80270078, - 0x80280071, 0x802F0078, 0x80400071, 0x807D0078, 0x80800006, 0x80810078, 0x808300AD, 0x808400AE, - 0x8085012D, 0x8086012E, 0x8087012F, 0x80880185, 0x80890186, 0x808A0187, 0x808B0188, 0x808C0184, - 0x808D01C9, 0x808E01CA, 0x808F01CB, 0x809001CC, 0x809101CD, 0x809201CE, 0x809301CF, 0x809401D0, - 0x809500BE, 0x809601D1, 0x809701D2, 0x809801D3, 0x809901D4, 0x809A0078, 0x809B0094, 0x80A0014E, - 0x80A10152, 0x80A20153, 0x80A30157, 0x80A40154, 0x80A50155, 0x80A60156, 0x80A70152, 0x80A80150, - 0x80A90153, 0x80AA01D5, 0x80AB0154, 0x80AC014F, 0x80AD0158, 0x80AF0152, 0x80B00154, 0x80B201D6, - 0x80B30150, 0x80B501D7, 0x80B60153, 0x80B80156, 0x80B90152, 0x80BA005F, 0x80BC0054, 0x80C50078, - 0x81800071, 0x818F0078, 0x8190012D, 0x819100BB, 0x81920078, 0x81980071, 0x81A50078, 0x81C00071, - 0x81CF0097, 0x81D00071, 0x81E20078, 0x81E40071, 0x81E8014F, 0x81E90154, 0x81EA0155, 0x81EB0078, - 0x8200015B, 0x8214015C, 0x82280071, 0x824F0078, 0x8250017E, 0x8251017F, 0x82520180, 0x82530181, - 0x82540182, 0x82550078, 0x8400009B, 0x84030078, 0x8405009B, 0x841C0078, 0x841F009B, 0x84200078, - 0x85000083, 0x85030078, 0x85060083, 0x8508009B, 0x851A0078, 0x851C0083, 0x851D0078, 0x851F0083, - 0x852001D8, 0x852101D9, 0x852201DA, 0x852301DB, 0x85240078, 0x8528009A, 0x852C0078, 0xE8000094, - 0xE87B0078, 0xE8800094, 0xE8930078, 0xE8950094, 0xE8AF0894, 0xE8B200A7, 0xE8B30083, 0xE8B50094, - 0xE8B600A7, 0xE8B90057, 0xE8BD0083, 0xE8C10094, 0xE8C20083, 0xE8C60094, 0xE8D50083, 0xE8D70094, - 0xE8DD0894, 0xE8E00094, 0xE8EF0078, 0xE9000054, 0xE9210083, 0xE9220054, 0xE9230078, 0xE9800054, - 0xE9AB0078, 0xEA002877, 0xEA0D2855, 0xEA1A2877, 0xEA272855, 0xEA2A0078, 0xEA2B2855, 0xEA342877, - 0xEA412855, 0xEA4E0078, 0xEA4F2877, 0xEA500078, 0xEA522877, 0xEA530078, 0xEA542877, 0xEA560078, - 0xEA572877, 0xEA5B2855, 0xEA682877, 0xEA752855, 0xEA822877, 0xEA850078, 0xEA862877, 0xEA8A0078, - 0xEA8B2877, 0xEA8E0078, 0xEA8F2855, 0xEA9C2877, 0xEA9F0078, 0xEAA02877, 0xEAA20078, 0xEAA52877, - 0xEAA80078, 0xEAA92855, 0xEAB62877, 0xEAC32855, 0xEAD02877, 0xEADD2855, 0xEAEA2877, 0xEAF72855, - 0xEB042877, 0xEB112855, 0xEB1E2877, 0xEB2B2855, 0xEB382877, 0xEB452855, 0xEB530078, 0xEB542877, - 0xEB6029DC, 0xEB612855, 0xEB6D29DC, 0xEB6E2855, 0xEB712877, 0xEB7D29DC, 0xEB7E2855, 0xEB8A29DC, - 0xEB8B2855, 0xEB8E2877, 0xEB9A29DC, 0xEB9B2855, 0xEBA729DC, 0xEBA82855, 0xEBAB2877, 0xEBB729DC, - 0xEBB82855, 0xEBC429DC, 0xEBC52855, 0xEBC82877, 0xEBD429DC, 0xEBD52855, 0xEBE129DC, 0xEBE22855, - 0xEBE50078, 0xEBE7280F, 0xEBE82811, 0xEBE92813, 0xEBEA2815, 0xEBEB2817, 0xEBEC280F, 0xEBED2811, - 0xEBEE2813, 0xEBEF2815, 0xEBF02817, 0xEBF1280F, 0xEBF22811, 0xEBF32813, 0xEBF42815, 0xEBF52817, - 0xEBF6280F, 0xEBF72811, 0xEBF82813, 0xEBF92815, 0xEBFA2817, 0xEBFB280F, 0xEBFC2811, 0xEBFD2813, - 0xEBFE2815, 0xEBFF2817, 0xEC000078 - }; - - static const uint32_t a17[] = { - 0x00000071, 0x536B0078, 0x7C000871, 0x7D0F0078 - }; - - static const uint32_t a23[] = { - 0x00000057, 0x00010078, 0x00100057, 0x00400078, 0x00800083, 0x00F80078, 0x8000013F, 0xFFFF0078 - }; - - static const uint32_t a24[] = { - 0x0000013F, 0x7FFF0078 - }; - - - // The full set of all arrays to be searched. - static const Range FULL_DATA[] = { - {sizeof(a0)/sizeof(uint32_t), a0}, - {sizeof(a1)/sizeof(uint32_t), a1}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {sizeof(a7)/sizeof(uint32_t), a7}, - {sizeof(a8)/sizeof(uint32_t), a8}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {sizeof(a16)/sizeof(uint32_t), a16}, - {sizeof(a17)/sizeof(uint32_t), a17}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {sizeof(a23)/sizeof(uint32_t), a23}, - {sizeof(a24)/sizeof(uint32_t), a24}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0} - }; - - // Array of uppercase differences - static const short UCDIFF[] = { - 0, -32, 743, 121, -1, -232, -300, 97, - 163, 130, 56, -2, -79, -210, -206, -205, - -202, -203, -207, -209, -211, -213, -214, -218, - -217, -219, -83, 84, -38, -37, -31, -64, - -63, -62, -57, -47, -54, -86, -80, 7, - -96, -48, -59, 8, 74, 86, 100, 128, - 112, 126, 9, -7205, -16, -26, -7264, -40 - }; - - // Array of lowercase differences - static const short LCDIFF[] = { - 0, 32, 1, -199, -121, 210, 206, 205, - 79, 202, 203, 207, 211, 209, 213, 214, - 218, 217, 219, 2, -97, -56, -130, -163, - 83, 38, 37, 64, 63, -60, -7, 80, - 48, 7264, -8, -74, -9, -86, -100, -112, - -128, -126, -7517, -8383, -8262, 16, 26, 40 - }; - - // Array of titlecase differences - static const short TCDIFF[] = { - 3, 1, 0, -1 - }; - - // Array of mirrored character differences - static const short MIRROR_DIFF[] = { - 0, 1, -1, 2, -2, 16, -16, 3, - -3, 2016, 138, 1824, 2104, 2108, 2106, -138, - 8, 7, -8, -7, -1824, -2016, -2104, -2106, - -2108 - }; - - // Array of all possible numeric values - static const int NUMERICS[] = { - -1, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, -2, 100, 1000, - 40, 50, 60, 70, 80, 90, 10000, 500, - 5000, 36, 37, 38, 39, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 200, 300, - 400, 600, 700, 800, 900, 2000, 3000, 4000, - 6000, 7000, 8000, 9000, 20000, 30000, 40000, 50000, - 60000, 70000, 80000, 90000 - }; - - // All possible packed data values, no duplicates - static const uint32_t PACKED_DATA[] = { - 0x00000000, 0x0000012F, 0x0000016F, 0x0000014F, 0x0000018F, 0x0000018C, 0x000001B8, 0x000000B8, - 0x000000BA, 0x020005B5, 0x040005B6, 0x00000099, 0x000000F8, 0x00000094, 0x02000069, 0x04000069, - 0x06000069, 0x08000069, 0x0A000069, 0x0C000069, 0x0E000069, 0x10000069, 0x12000069, 0x14000069, - 0x060005B9, 0x000001B9, 0x080005B9, 0x16020001, 0x18020001, 0x1A020001, 0x1C020001, 0x1E020001, - 0x20020001, 0x22020001, 0x24020001, 0x26020001, 0x28020001, 0x2A020001, 0x2C020001, 0x2E020001, - 0x30020001, 0x32020001, 0x34020001, 0x36020001, 0x38020001, 0x3A020001, 0x3C020001, 0x3E020001, - 0x40020001, 0x42020001, 0x44020001, 0x46020001, 0x48020001, 0x060005B5, 0x080005B6, 0x000001BB, - 0x000001B7, 0x16000802, 0x18000802, 0x1A000802, 0x1C000802, 0x1E000802, 0x20000802, 0x22000802, - 0x24000802, 0x26000802, 0x28000802, 0x2A000802, 0x2C000802, 0x2E000802, 0x30000802, 0x32000802, - 0x34000802, 0x36000802, 0x38000802, 0x3A000802, 0x3C000802, 0x3E000802, 0x40000802, 0x42000802, - 0x44000802, 0x46000802, 0x48000802, 0x000000EC, 0x000001BC, 0x00000002, 0x0A0005BD, 0x00000130, - 0x000000BC, 0x000000B9, 0x0600006B, 0x0800006B, 0x00001002, 0x0400006B, 0x0C0005BE, 0x4A0001AB, - 0x00020001, 0x00000802, 0x00001802, 0x00040001, 0x00060001, 0x00002002, 0x00080001, 0x000C0001, - 0x000E0001, 0x00100001, 0x00140001, 0x00160001, 0x00180001, 0x00004002, 0x00004802, 0x00200001, - 0x00220001, 0x00000005, 0x00A60001, 0x01805802, 0x01042003, 0x00280001, 0x002C0001, 0x00000001, - 0x00000000, 0x00007002, 0x00007802, 0x00009802, 0x0000A802, 0x0000B802, 0x0000C002, 0x0000C802, - 0x0000D002, 0x00000004, 0x000001A4, 0x00000106, 0x00320001, 0x00340001, 0x00360001, 0x00380001, - 0x0000E002, 0x0000E802, 0x0000F002, 0x0000F802, 0x00010002, 0x00010802, 0x00012002, 0x00012802, - 0x00013802, 0x003A0001, 0x003E0001, 0x00013002, 0x0000001C, 0x00000107, 0x00400001, 0x00000018, - 0x00014802, 0x000001B4, 0x00000038, 0x00000025, 0x00000050, 0x00000058, 0x00000045, 0x00000044, - 0x020000C9, 0x060000C9, 0x0A0000C9, 0x0E0000C9, 0x120000C9, 0x000000D8, 0x0000005C, 0x00000008, - 0x02000009, 0x06000009, 0x0A000009, 0x0E000009, 0x12000009, 0x0400000B, 0x0800000B, 0x0000000B, - 0x1600000B, 0x4E00000B, 0x00000006, 0x4A00000B, 0x000001B5, 0x00420001, 0x0600000B, 0x0A00000B, - 0x0E00000B, 0x1200000B, 0x3E00000B, 0x5200000B, 0x5600000B, 0x5A00000B, 0x5C00000B, 0x000001B6, - 0x2400000A, 0x2800000A, 0x00000010, 0x020001AB, 0x060001AB, 0x0A0001AB, 0x0E0001AB, 0x120001AB, - 0x00000108, 0x00015802, 0x00440001, 0x00016002, 0x00016802, 0x00017002, 0x00017802, 0x00018002, - 0x00018802, 0x00440003, 0x00460001, 0x00480003, 0x00019802, 0x004A0001, 0x004C0001, 0x004E0001, - 0x003C0001, 0x00500001, 0x00520001, 0x000001BD, 0x0000018D, 0x000001D0, 0x00000250, 0x00000230, - 0x040005BE, 0x000000F9, 0x0200006B, 0x0A00006B, 0x0E00006B, 0x1200006B, 0x00540001, 0x00560001, - 0x000005B9, 0x045A000A, 0x085A000A, 0x0C5A000A, 0x105A000A, 0x145A000A, 0x185A000A, 0x525A000A, - 0x5E5A000A, 0x0401A00A, 0x0801A00A, 0x0C01A00A, 0x1001A00A, 0x1401A00A, 0x1801A00A, 0x5201A00A, - 0x5E01A00A, 0x4E00000A, 0x5C00000A, 0x0E0005B9, 0x100005B9, 0x020005B9, 0x040005B9, 0x160005B9, - 0x180005B9, 0x1A0005B9, 0x200005B9, 0x220005B9, 0x240005B9, 0x260005B9, 0x040001AB, 0x080001AB, - 0x0C0001AB, 0x100001AB, 0x140001AB, 0x180001AB, 0x1C0001AB, 0x200001AB, 0x240001AB, 0x280001AB, - 0x0C00006B, 0x1000006B, 0x1400006B, 0x1800006B, 0x1C00006B, 0x2000006B, 0x2400006B, 0x2800006B, - 0x005C001C, 0x0001A81C, 0x1A0001AB, 0x1E0001AB, 0x220001AB, 0x260001AB, 0x2A0001AB, 0x160001AB, - 0x020005B6, 0x100005B6, 0x280005B9, 0x2C0005B9, 0x300005B9, 0x0001B002, 0x020005BD, 0x0600000A, - 0x0A00000A, 0x0E00000A, 0x1200000A, 0x1600000A, 0x3E00000A, 0x0C00000B, 0x1000000B, 0x1400000B, - 0x2E0001AB, 0x320001AB, 0x360001AB, 0x3A0001AB, 0x3E0001AB, 0x420001AB, 0x460001AB, 0x640001AB, - 0x680001AB, 0x6A0001AB, 0x6E0001AB, 0x720001AB, 0x760001AB, 0x7A0001AB, 0x00000013, 0x00000012, - 0x0000005A, 0x000001B0, 0x7C00000B, 0x8000000B, 0x8200000B, 0x8600000B, 0x8C00000B, 0x6000000B, - 0x9200000B, 0x9600000B, 0x9800000B, 0x9C00000B, 0xA000000B, 0xA400000B, 0x4A0001AA, 0x040001AA, - 0x520001AA, 0x600001AA, 0x0C0001AA, 0x5E0001AA, 0x160001AA, 0x4C0001AA, 0x4E0001AA, 0x9E0001AA, - 0x060001AA, 0x8800000A, 0x2A0001AA, 0x005E0001, 0x0001B802, 0x0400002B, 0x0800002B, 0x1600002B, - 0x4C00002B, 0x00002802, 0x00003002, 0x000A0001, 0x00120001, 0x00003802, 0x001A0001, 0x001C0001, - 0x001E0001, 0x00240001, 0x00005002, 0x00006002, 0x002A0001, 0x002E0001, 0x00300001, 0x00006802, - 0x00008002, 0x00008802, 0x00009002, 0x0000A002, 0x0000B002, 0x0000D906, 0x00011002, 0x00011802, - 0x00014002, 0x040000C9, 0x080000C9, 0x0C0000C9, 0x100000C9, 0x140000C9, 0x04000009, 0x08000009, - 0x0C000009, 0x10000009, 0x14000009, 0x2200000B, 0x4C00000B, 0x2A00000B, 0x5000000B, 0x5400000B, - 0x5800000B, 0x2600000A, 0x00015002, 0x00019002, 0x00000030, 0x000001BE, 0x0000014E, 0x00000210, - 0x000001F0, 0x00580001, 0x065A000A, 0x0A5A000A, 0x0E5A000A, 0x125A000A, 0x165A000A, 0x1A5A000A, - 0x4C5A000A, 0x4E5A000A, 0x0601A00A, 0x0A01A00A, 0x0E01A00A, 0x1201A00A, 0x1601A00A, 0x1A01A00A, - 0x4C01A00A, 0x4E01A00A, 0x6000000A, 0x0000000A, 0x120005B9, 0x140005B9, 0x1C0005B9, 0x1E0005B9, - 0x1600006B, 0x1A00006B, 0x1E00006B, 0x2200006B, 0x2600006B, 0x2A00006B, 0x0E0005B5, 0x040005B5, - 0x2A0005B9, 0x2E0005B9, 0x0200000A, 0x0400000A, 0x0800000A, 0x0C00000A, 0x1000000A, 0x1400000A, - 0x2A00000A, 0x2C0001AB, 0x300001AB, 0x340001AB, 0x380001AB, 0x3C0001AB, 0x400001AB, 0x440001AB, - 0x480001AB, 0x620001AB, 0x660001AB, 0x500001AB, 0x6C0001AB, 0x700001AB, 0x740001AB, 0x780001AB, - 0x520001AB, 0x7E00000B, 0x5E00000B, 0x8400000B, 0x8800000B, 0x8A00000B, 0x8E00000B, 0x9000000B, - 0x9400000B, 0x9A00000B, 0x9E00000B, 0xA200000B, 0xA600000B, 0x5C0001AA, 0x3E0001AA, 0x7E0001AA, - 0x0600002B, 0x0A00002B, 0x2A00002B, 0x4E00002B, 0x00000019 - }; -} diff --git a/libs/utils/executablepath_darwin.cpp b/libs/utils/executablepath_darwin.cpp deleted file mode 100644 index 2e3c3a0..0000000 --- a/libs/utils/executablepath_darwin.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/executablepath.h> -#import <Carbon/Carbon.h> -#include <unistd.h> - -void executablepath(char s[PATH_MAX]) -{ - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - CFDictionaryRef dict; - dict = ProcessInformationCopyDictionary(&psn, 0xffffffff); - CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict, - CFSTR("CFBundleExecutable")); - CFStringGetCString(value, s, PATH_MAX+1, kCFStringEncodingUTF8); -} - diff --git a/libs/utils/executablepath_linux.cpp b/libs/utils/executablepath_linux.cpp deleted file mode 100644 index b8d2a3d..0000000 --- a/libs/utils/executablepath_linux.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/executablepath.h> -#include <sys/types.h> -#include <unistd.h> -#include <limits.h> -#include <stdio.h> - -void executablepath(char exe[PATH_MAX]) -{ - char proc[100]; - sprintf(proc, "/proc/%d/exe", getpid()); - - int err = readlink(proc, exe, PATH_MAX); -} - diff --git a/libs/utils/futex_synchro.c b/libs/utils/futex_synchro.c deleted file mode 100644 index ba19520..0000000 --- a/libs/utils/futex_synchro.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <limits.h> - -#include <sys/time.h> -#include <sched.h> - -#include <errno.h> - -#include <private/utils/futex_synchro.h> - - -// This futex glue code is need on desktop linux, but is already part of bionic. -#if !defined(HAVE_FUTEX_WRAPPERS) - -#include <sys/syscall.h> -typedef unsigned int u32; -#define asmlinkage -#define __user -#include <linux/futex.h> -#include <utils/Atomic.h> - - -int futex (int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3) -{ - int err = syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3); - return err == 0 ? 0 : -errno; -} - -int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout) -{ - return futex((int*)ftx, FUTEX_WAIT, val, timeout, NULL, 0); -} - -int __futex_wake(volatile void *ftx, int count) -{ - return futex((int*)ftx, FUTEX_WAKE, count, NULL, NULL, 0); -} - -int __atomic_cmpxchg(int old, int _new, volatile int *ptr) -{ - return android_atomic_cmpxchg(old, _new, ptr); -} - -int __atomic_swap(int _new, volatile int *ptr) -{ - return android_atomic_swap(_new, ptr); -} - -int __atomic_dec(volatile int *ptr) -{ - return android_atomic_dec(ptr); -} - -#else // !defined(__arm__) - -int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout); -int __futex_wake(volatile void *ftx, int count); - -int __atomic_cmpxchg(int old, int _new, volatile int *ptr); -int __atomic_swap(int _new, volatile int *ptr); -int __atomic_dec(volatile int *ptr); - -#endif // !defined(HAVE_FUTEX_WRAPPERS) - - -// lock states -// -// 0: unlocked -// 1: locked, no waiters -// 2: locked, maybe waiters - -void futex_mutex_init(futex_mutex_t *m) -{ - m->value = 0; -} - -int futex_mutex_lock(futex_mutex_t *m, unsigned msec) -{ - if(__atomic_cmpxchg(0, 1, &m->value) == 0) { - return 0; - } - if(msec == FUTEX_WAIT_INFINITE) { - while(__atomic_swap(2, &m->value) != 0) { - __futex_wait(&m->value, 2, 0); - } - } else { - struct timespec ts; - ts.tv_sec = msec / 1000; - ts.tv_nsec = (msec % 1000) * 1000000; - while(__atomic_swap(2, &m->value) != 0) { - if(__futex_wait(&m->value, 2, &ts) == -ETIMEDOUT) { - return -1; - } - } - } - return 0; -} - -int futex_mutex_trylock(futex_mutex_t *m) -{ - if(__atomic_cmpxchg(0, 1, &m->value) == 0) { - return 0; - } - return -1; -} - -void futex_mutex_unlock(futex_mutex_t *m) -{ - if(__atomic_dec(&m->value) != 1) { - m->value = 0; - __futex_wake(&m->value, 1); - } -} - -/* XXX *technically* there is a race condition that could allow - * XXX a signal to be missed. If thread A is preempted in _wait() - * XXX after unlocking the mutex and before waiting, and if other - * XXX threads call signal or broadcast UINT_MAX times (exactly), - * XXX before thread A is scheduled again and calls futex_wait(), - * XXX then the signal will be lost. - */ - -void futex_cond_init(futex_cond_t *c) -{ - c->value = 0; -} - -int futex_cond_wait(futex_cond_t *c, futex_mutex_t *m, unsigned msec) -{ - if(msec == FUTEX_WAIT_INFINITE){ - int oldvalue = c->value; - futex_mutex_unlock(m); - __futex_wait(&c->value, oldvalue, 0); - futex_mutex_lock(m, FUTEX_WAIT_INFINITE); - return 0; - } else { - int oldvalue = c->value; - struct timespec ts; - ts.tv_sec = msec / 1000; - ts.tv_nsec = (msec % 1000) * 1000000; - futex_mutex_unlock(m); - const int err = __futex_wait(&c->value, oldvalue, &ts); - futex_mutex_lock(m, FUTEX_WAIT_INFINITE); - return err; - } -} - -void futex_cond_signal(futex_cond_t *c) -{ - __atomic_dec(&c->value); - __futex_wake(&c->value, 1); -} - -void futex_cond_broadcast(futex_cond_t *c) -{ - __atomic_dec(&c->value); - __futex_wake(&c->value, INT_MAX); -} - diff --git a/libs/utils/misc.cpp b/libs/utils/misc.cpp deleted file mode 100644 index dc89d15..0000000 --- a/libs/utils/misc.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Miscellaneous utility functions. -// -#include <utils/misc.h> - -#include <sys/stat.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <stdio.h> - -using namespace android; - -namespace android { - -/* - * Like strdup(), but uses C++ "new" operator instead of malloc. - */ -char* strdupNew(const char* str) -{ - char* newStr; - int len; - - if (str == NULL) - return NULL; - - len = strlen(str); - newStr = new char[len+1]; - memcpy(newStr, str, len+1); - - return newStr; -} - -/* - * Concatenate an argument vector. - */ -char* concatArgv(int argc, const char* const argv[]) -{ - char* newStr = NULL; - int len, totalLen, posn, idx; - - /* - * First, figure out the total length. - */ - totalLen = idx = 0; - while (1) { - if (idx == argc || argv[idx] == NULL) - break; - if (idx) - totalLen++; // leave a space between args - totalLen += strlen(argv[idx]); - idx++; - } - - /* - * Alloc the string. - */ - newStr = new char[totalLen +1]; - if (newStr == NULL) - return NULL; - - /* - * Finally, allocate the string and copy data over. - */ - idx = posn = 0; - while (1) { - if (idx == argc || argv[idx] == NULL) - break; - if (idx) - newStr[posn++] = ' '; - - len = strlen(argv[idx]); - memcpy(&newStr[posn], argv[idx], len); - posn += len; - - idx++; - } - - assert(posn == totalLen); - newStr[posn] = '\0'; - - return newStr; -} - -/* - * Count the #of args in an argument vector. Don't count the final NULL. - */ -int countArgv(const char* const argv[]) -{ - int count = 0; - - while (argv[count] != NULL) - count++; - - return count; -} - - -#include <stdio.h> -/* - * Get a file's type. - */ -FileType getFileType(const char* fileName) -{ - struct stat sb; - - if (stat(fileName, &sb) < 0) { - if (errno == ENOENT || errno == ENOTDIR) - return kFileTypeNonexistent; - else { - fprintf(stderr, "getFileType got errno=%d on '%s'\n", - errno, fileName); - return kFileTypeUnknown; - } - } else { - if (S_ISREG(sb.st_mode)) - return kFileTypeRegular; - else if (S_ISDIR(sb.st_mode)) - return kFileTypeDirectory; - else if (S_ISCHR(sb.st_mode)) - return kFileTypeCharDev; - else if (S_ISBLK(sb.st_mode)) - return kFileTypeBlockDev; - else if (S_ISFIFO(sb.st_mode)) - return kFileTypeFifo; -#ifdef HAVE_SYMLINKS - else if (S_ISLNK(sb.st_mode)) - return kFileTypeSymlink; - else if (S_ISSOCK(sb.st_mode)) - return kFileTypeSocket; -#endif - else - return kFileTypeUnknown; - } -} - -/* - * Get a file's modification date. - */ -time_t getFileModDate(const char* fileName) -{ - struct stat sb; - - if (stat(fileName, &sb) < 0) - return (time_t) -1; - - return sb.st_mtime; -} - -/* - * Round up to the next highest power of 2. - * - * Found on http://graphics.stanford.edu/~seander/bithacks.html. - */ -unsigned int roundUpPower2(unsigned int val) -{ - val--; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val++; - - return val; -} - -}; // namespace android - diff --git a/libs/utils/ported.cpp b/libs/utils/ported.cpp deleted file mode 100644 index 656e46f..0000000 --- a/libs/utils/ported.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Ports of standard functions that don't exist on a specific platform. -// -// Note these are NOT in the "android" namespace. -// -#include <utils/ported.h> - -#if defined(NEED_GETTIMEOFDAY) || defined(NEED_USLEEP) -# include <sys/time.h> -# include <windows.h> -#endif - - -#if defined(NEED_GETTIMEOFDAY) -/* - * Replacement gettimeofday() for Windows environments (primarily MinGW). - * - * Ignores "tz". - */ -int gettimeofday(struct timeval* ptv, struct timezone* tz) -{ - long long nsTime; // time in 100ns units since Jan 1 1601 - FILETIME ft; - - if (tz != NULL) { - // oh well - } - - ::GetSystemTimeAsFileTime(&ft); - nsTime = (long long) ft.dwHighDateTime << 32 | - (long long) ft.dwLowDateTime; - // convert to time in usec since Jan 1 1970 - ptv->tv_usec = (long) ((nsTime / 10LL) % 1000000LL); - ptv->tv_sec = (long) ((nsTime - 116444736000000000LL) / 10000000LL); - - return 0; -} -#endif - -#if defined(NEED_USLEEP) -// -// Replacement usleep for Windows environments (primarily MinGW). -// -void usleep(unsigned long usec) -{ - // Win32 API function Sleep() takes milliseconds - ::Sleep((usec + 500) / 1000); -} -#endif - -#if 0 //defined(NEED_PIPE) -// -// Replacement pipe() command for MinGW -// -// The _O_NOINHERIT flag sets bInheritHandle to FALSE in the -// SecurityAttributes argument to CreatePipe(). This means the handles -// aren't inherited when a new process is created. The examples I've seen -// use it, possibly because there's a lot of junk going on behind the -// scenes. (I'm assuming "process" and "thread" are different here, so -// we should be okay spinning up a thread.) The recommended practice is -// to dup() the descriptor you want the child to have. -// -// It appears that unnamed pipes can't do non-blocking ("overlapped") I/O. -// You can't use select() either, since that only works on sockets. The -// Windows API calls that are useful here all operate on a HANDLE, not -// an integer file descriptor, and I don't think you can get there from -// here. The "named pipe" stuff is insane. -// -int pipe(int filedes[2]) -{ - return _pipe(filedes, 0, _O_BINARY | _O_NOINHERIT); -} -#endif - -#if defined(NEED_SETENV) -/* - * MinGW lacks these. For now, just stub them out so the code compiles. - */ -int setenv(const char* name, const char* value, int overwrite) -{ - return 0; -} -void unsetenv(const char* name) -{ -} -char* getenv(const char* name) -{ - return NULL; -} -#endif |