diff options
34 files changed, 783 insertions, 96 deletions
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index 7710c5b2d4..b8f505e5cc 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -33,7 +33,7 @@ #include "private/android_filesystem_config.h" #define LOG_TAG "dumpstate" -#include <utils/Log.h> +#include <cutils/log.h> #include "dumpstate.h" diff --git a/data/etc/android.hardware.nfc.hce.xml b/data/etc/android.hardware.nfc.hce.xml new file mode 100644 index 0000000000..10b96b1d78 --- /dev/null +++ b/data/etc/android.hardware.nfc.hce.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> + +<!-- This feature indicates that the device supports host-based + NFC card emulation --> +<permissions> + <feature name="android.hardware.nfc.hce" /> +</permissions> diff --git a/include/batteryservice/BatteryService.h b/include/batteryservice/BatteryService.h new file mode 100644 index 0000000000..855262b334 --- /dev/null +++ b/include/batteryservice/BatteryService.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2013 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_BATTERYSERVICE_H +#define ANDROID_BATTERYSERVICE_H + +#include <binder/Parcel.h> +#include <utils/Errors.h> +#include <utils/String8.h> + +namespace android { + +// must be kept in sync with definitions in BatteryManager.java +enum { + BATTERY_STATUS_UNKNOWN = 1, // equals BatteryManager.BATTERY_STATUS_UNKNOWN constant + BATTERY_STATUS_CHARGING = 2, // equals BatteryManager.BATTERY_STATUS_CHARGING constant + BATTERY_STATUS_DISCHARGING = 3, // equals BatteryManager.BATTERY_STATUS_DISCHARGING constant + BATTERY_STATUS_NOT_CHARGING = 4, // equals BatteryManager.BATTERY_STATUS_NOT_CHARGING constant + BATTERY_STATUS_FULL = 5, // equals BatteryManager.BATTERY_STATUS_FULL constant +}; + +// must be kept in sync with definitions in BatteryManager.java +enum { + BATTERY_HEALTH_UNKNOWN = 1, // equals BatteryManager.BATTERY_HEALTH_UNKNOWN constant + BATTERY_HEALTH_GOOD = 2, // equals BatteryManager.BATTERY_HEALTH_GOOD constant + BATTERY_HEALTH_OVERHEAT = 3, // equals BatteryManager.BATTERY_HEALTH_OVERHEAT constant + BATTERY_HEALTH_DEAD = 4, // equals BatteryManager.BATTERY_HEALTH_DEAD constant + BATTERY_HEALTH_OVER_VOLTAGE = 5, // equals BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE constant + BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6, // equals BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE constant + BATTERY_HEALTH_COLD = 7, // equals BatteryManager.BATTERY_HEALTH_COLD constant +}; + +struct BatteryProperties { + bool chargerAcOnline; + bool chargerUsbOnline; + bool chargerWirelessOnline; + int batteryStatus; + int batteryHealth; + bool batteryPresent; + int batteryLevel; + int batteryVoltage; + int batteryTemperature; + String8 batteryTechnology; + + status_t writeToParcel(Parcel* parcel) const; + status_t readFromParcel(Parcel* parcel); +}; + +}; // namespace android + +#endif // ANDROID_BATTERYSERVICE_H diff --git a/include/batteryservice/IBatteryPropertiesListener.h b/include/batteryservice/IBatteryPropertiesListener.h new file mode 100644 index 0000000000..b02d8e9073 --- /dev/null +++ b/include/batteryservice/IBatteryPropertiesListener.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 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_IBATTERYPROPERTIESLISTENER_H +#define ANDROID_IBATTERYPROPERTIESLISTENER_H + +#include <binder/IBinder.h> +#include <binder/IInterface.h> + +#include <batteryservice/BatteryService.h> + +namespace android { + +// must be kept in sync with interface defined in IBatteryPropertiesListener.aidl +enum { + TRANSACT_BATTERYPROPERTIESCHANGED = IBinder::FIRST_CALL_TRANSACTION, +}; + +// ---------------------------------------------------------------------------- + +class IBatteryPropertiesListener : public IInterface { +public: + DECLARE_META_INTERFACE(BatteryPropertiesListener); + + virtual void batteryPropertiesChanged(struct BatteryProperties props) = 0; +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_IBATTERYPROPERTIESLISTENER_H diff --git a/include/batteryservice/IBatteryPropertiesRegistrar.h b/include/batteryservice/IBatteryPropertiesRegistrar.h new file mode 100644 index 0000000000..8d28b1d35f --- /dev/null +++ b/include/batteryservice/IBatteryPropertiesRegistrar.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 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_IBATTERYPROPERTIESREGISTRAR_H +#define ANDROID_IBATTERYPROPERTIESREGISTRAR_H + +#include <binder/IInterface.h> +#include <batteryservice/IBatteryPropertiesListener.h> + +namespace android { + +// must be kept in sync with interface defined in IBatteryPropertiesRegistrar.aidl +enum { + REGISTER_LISTENER = IBinder::FIRST_CALL_TRANSACTION, + UNREGISTER_LISTENER, +}; + +class IBatteryPropertiesRegistrar : public IInterface { +public: + DECLARE_META_INTERFACE(BatteryPropertiesRegistrar); + + virtual void registerListener(const sp<IBatteryPropertiesListener>& listener) = 0; + virtual void unregisterListener(const sp<IBatteryPropertiesListener>& listener) = 0; +}; + +class BnBatteryPropertiesRegistrar : public BnInterface<IBatteryPropertiesRegistrar> { +public: + virtual status_t onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IBATTERYPROPERTIESREGISTRAR_H diff --git a/include/binder/BufferedTextOutput.h b/include/binder/BufferedTextOutput.h index adf3c32a87..9a7c43bb13 100644 --- a/include/binder/BufferedTextOutput.h +++ b/include/binder/BufferedTextOutput.h @@ -19,7 +19,7 @@ #include <binder/TextOutput.h> #include <utils/threads.h> -#include <cutils/uio.h> +#include <sys/uio.h> // --------------------------------------------------------------------------- namespace android { diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index d8256c191f..1419b451f8 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -67,10 +67,11 @@ public: float resolution; }; - void initialize(int32_t id, int32_t generation, const InputDeviceIdentifier& identifier, - const String8& alias, bool isExternal); + void initialize(int32_t id, int32_t generation, int32_t controllerNumber, + const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal); inline int32_t getId() const { return mId; } + inline int32_t getControllerNumber() const { return mControllerNumber; } inline int32_t getGeneration() const { return mGeneration; } inline const InputDeviceIdentifier& getIdentifier() const { return mIdentifier; } inline const String8& getAlias() const { return mAlias; } @@ -111,6 +112,7 @@ public: private: int32_t mId; int32_t mGeneration; + int32_t mControllerNumber; InputDeviceIdentifier mIdentifier; String8 mAlias; bool mIsExternal; diff --git a/include/utils/BasicHashtable.h b/include/utils/BasicHashtable.h index 7a6c96cefc..c235d62526 100644 --- a/include/utils/BasicHashtable.h +++ b/include/utils/BasicHashtable.h @@ -52,6 +52,7 @@ protected: BasicHashtableImpl(size_t entrySize, bool hasTrivialDestructor, size_t minimumInitialCapacity, float loadFactor); BasicHashtableImpl(const BasicHashtableImpl& other); + virtual ~BasicHashtableImpl(); void dispose(); diff --git a/include/utils/ThreadDefs.h b/include/utils/ThreadDefs.h index a8f8eb3d90..9711c13792 100644 --- a/include/utils/ThreadDefs.h +++ b/include/utils/ThreadDefs.h @@ -20,6 +20,7 @@ #include <stdint.h> #include <sys/types.h> #include <system/graphics.h> +#include <system/thread_defs.h> // --------------------------------------------------------------------------- // C API @@ -32,53 +33,6 @@ typedef void* android_thread_id_t; typedef int (*android_thread_func_t)(void*); -enum { - /* - * *********************************************** - * ** Keep in sync with android.os.Process.java ** - * *********************************************** - * - * This maps directly to the "nice" priorities we use in Android. - * A thread priority should be chosen inverse-proportionally to - * the amount of work the thread is expected to do. The more work - * a thread will do, the less favorable priority it should get so that - * it doesn't starve the system. Threads not behaving properly might - * be "punished" by the kernel. - * Use the levels below when appropriate. Intermediate values are - * acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below. - */ - ANDROID_PRIORITY_LOWEST = 19, - - /* use for background tasks */ - ANDROID_PRIORITY_BACKGROUND = 10, - - /* most threads run at normal priority */ - ANDROID_PRIORITY_NORMAL = 0, - - /* threads currently running a UI that the user is interacting with */ - ANDROID_PRIORITY_FOREGROUND = -2, - - /* the main UI thread has a slightly more favorable priority */ - ANDROID_PRIORITY_DISPLAY = -4, - - /* ui service treads might want to run at a urgent display (uncommon) */ - ANDROID_PRIORITY_URGENT_DISPLAY = HAL_PRIORITY_URGENT_DISPLAY, - - /* all normal audio threads */ - ANDROID_PRIORITY_AUDIO = -16, - - /* service audio threads (uncommon) */ - ANDROID_PRIORITY_URGENT_AUDIO = -19, - - /* should never be used in practice. regular process might not - * be allowed to use this level */ - ANDROID_PRIORITY_HIGHEST = -20, - - ANDROID_PRIORITY_DEFAULT = ANDROID_PRIORITY_NORMAL, - ANDROID_PRIORITY_MORE_FAVORABLE = -1, - ANDROID_PRIORITY_LESS_FAVORABLE = +1, -}; - #ifdef __cplusplus } // extern "C" #endif diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk index 4c8820e801..f3f8dafc2a 100644 --- a/libs/binder/Android.mk +++ b/libs/binder/Android.mk @@ -47,5 +47,6 @@ include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_LDLIBS += -lpthread LOCAL_MODULE := libbinder +LOCAL_STATIC_LIBRARIES += libutils LOCAL_SRC_FILES := $(sources) include $(BUILD_STATIC_LIBRARY) diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp index 99c27476c7..61b4f7d661 100644 --- a/libs/binder/AppOpsManager.cpp +++ b/libs/binder/AppOpsManager.cpp @@ -31,6 +31,7 @@ static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) { if (gToken == NULL) { gToken = service->getToken(new BBinder()); } + pthread_mutex_unlock(&gTokenMutex); return gToken; } diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 1750640fc1..a341ca8ed5 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -37,9 +37,11 @@ sp<IServiceManager> defaultServiceManager() { AutoMutex _l(gDefaultServiceManagerLock); - if (gDefaultServiceManager == NULL) { + while (gDefaultServiceManager == NULL) { gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL)); + if (gDefaultServiceManager == NULL) + sleep(1); } } diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 294e1d4898..c1e49bc8f6 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -194,6 +194,33 @@ sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) // in getWeakProxyForHandle() for more info about this. IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { + if (handle == 0) { + // Special case for context manager... + // The context manager is the only object for which we create + // a BpBinder proxy without already holding a reference. + // Perform a dummy transaction to ensure the context manager + // is registered before we create the first local reference + // to it (which will occur when creating the BpBinder). + // If a local reference is created for the BpBinder when the + // context manager is not present, the driver will fail to + // provide a reference to the context manager, but the + // driver API does not return status. + // + // Note that this is not race-free if the context manager + // dies while this code runs. + // + // TODO: add a driver API to wait for context manager, or + // stop special casing handle 0 for context manager and add + // a driver API to get a handle to the context manager with + // proper reference counting. + + Parcel data; + status_t status = IPCThreadState::self()->transact( + 0, IBinder::PING_TRANSACTION, data, NULL, 0); + if (status == DEAD_OBJECT) + return NULL; + } + b = new BpBinder(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 320f4cf738..95ba09528a 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -853,13 +853,13 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) { if (presentWhen != 0 && desiredPresent > presentWhen && desiredPresent - presentWhen < MAX_FUTURE_NSEC) { - ALOGV("pts defer: des=%lld when=%lld (%lld) now=%lld", + ST_LOGV("pts defer: des=%lld when=%lld (%lld) now=%lld", desiredPresent, presentWhen, desiredPresent - presentWhen, systemTime(CLOCK_MONOTONIC)); return PRESENT_LATER; } if (presentWhen != 0) { - ALOGV("pts accept: %p[%d] sig=%lld des=%lld when=%lld (%lld)", + ST_LOGV("pts accept: %p[%d] sig=%lld des=%lld when=%lld (%lld)", mSlots, buf, mSlots[buf].mFence->getSignalTime(), desiredPresent, presentWhen, desiredPresent - presentWhen); } @@ -899,35 +899,31 @@ status_t BufferQueue::releaseBuffer( ATRACE_CALL(); ATRACE_BUFFER_INDEX(buf); - Mutex::Autolock _l(mMutex); - if (buf == INVALID_BUFFER_SLOT || fence == NULL) { return BAD_VALUE; } - // Check if this buffer slot is on the queue - bool slotQueued = false; - Fifo::iterator front(mQueue.begin()); - while (front != mQueue.end() && !slotQueued) { - if (front->mBuf == buf) - slotQueued = true; - front++; - } + Mutex::Autolock _l(mMutex); // If the frame number has changed because buffer has been reallocated, // we can ignore this releaseBuffer for the old buffer. if (frameNumber != mSlots[buf].mFrameNumber) { - // This should only occur if new buffer is still in the queue - ALOGE_IF(!slotQueued, - "received old buffer(#%lld) after new buffer(#%lld) on same " - "slot #%d already acquired", frameNumber, - mSlots[buf].mFrameNumber, buf); return STALE_BUFFER_SLOT; } - // this should never happen - ALOGE_IF(slotQueued, - "received new buffer(#%lld) on slot #%d that has not yet been " - "acquired", frameNumber, buf); + + + // Internal state consistency checks: + // Make sure this buffers hasn't been queued while we were owning it (acquired) + Fifo::iterator front(mQueue.begin()); + Fifo::const_iterator const end(mQueue.end()); + while (front != end) { + if (front->mBuf == buf) { + LOG_ALWAYS_FATAL("[%s] received new buffer(#%lld) on slot #%d that has not yet been " + "acquired", mConsumerName.string(), frameNumber, buf); + break; // never reached + } + front++; + } // The buffer can now only be released if its in the acquired state if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { @@ -1017,8 +1013,7 @@ status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) { return NO_ERROR; } -status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) -{ +status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) { ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h); if (!w || !h) { ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 54703d4fc3..b11110a18c 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -127,26 +127,25 @@ String8 getInputDeviceConfigurationFilePathByName( // --- InputDeviceInfo --- InputDeviceInfo::InputDeviceInfo() { - initialize(-1, -1, InputDeviceIdentifier(), String8(), false); + initialize(-1, 0, -1, InputDeviceIdentifier(), String8(), false); } InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : - mId(other.mId), mGeneration(other.mGeneration), mIdentifier(other.mIdentifier), - mAlias(other.mAlias), mIsExternal(other.mIsExternal), mSources(other.mSources), - mKeyboardType(other.mKeyboardType), - mKeyCharacterMap(other.mKeyCharacterMap), - mHasVibrator(other.mHasVibrator), - mHasButtonUnderPad(other.mHasButtonUnderPad), - mMotionRanges(other.mMotionRanges) { + mId(other.mId), mGeneration(other.mGeneration), mControllerNumber(other.mControllerNumber), + mIdentifier(other.mIdentifier), mAlias(other.mAlias), mIsExternal(other.mIsExternal), + mSources(other.mSources), mKeyboardType(other.mKeyboardType), + mKeyCharacterMap(other.mKeyCharacterMap), mHasVibrator(other.mHasVibrator), + mHasButtonUnderPad(other.mHasButtonUnderPad), mMotionRanges(other.mMotionRanges) { } InputDeviceInfo::~InputDeviceInfo() { } -void InputDeviceInfo::initialize(int32_t id, int32_t generation, +void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber, const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal) { mId = id; mGeneration = generation; + mControllerNumber = controllerNumber; mIdentifier = identifier; mAlias = alias; mIsExternal = isExternal; diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index 42e1c7e689..abf4b2e334 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -66,6 +66,7 @@ ifeq ($(HOST_OS), linux) LOCAL_SRC_FILES += Looper.cpp endif LOCAL_MODULE:= libutils +LOCAL_STATIC_LIBRARIES := liblog LOCAL_CFLAGS += $(host_commonCflags) LOCAL_LDLIBS += $(host_commonLdlibs) include $(BUILD_HOST_STATIC_LIBRARY) @@ -79,6 +80,7 @@ ifeq ($(HOST_OS), linux) LOCAL_SRC_FILES += Looper.cpp endif LOCAL_MODULE:= lib64utils +LOCAL_STATIC_LIBRARIES := liblog LOCAL_CFLAGS += $(host_commonCflags) -m64 LOCAL_LDLIBS += $(host_commonLdlibs) include $(BUILD_HOST_STATIC_LIBRARY) diff --git a/libs/utils/BasicHashtable.cpp b/libs/utils/BasicHashtable.cpp index fd51b7b2e0..491d9e98b4 100644 --- a/libs/utils/BasicHashtable.cpp +++ b/libs/utils/BasicHashtable.cpp @@ -42,6 +42,10 @@ BasicHashtableImpl::BasicHashtableImpl(const BasicHashtableImpl& other) : } } +BasicHashtableImpl::~BasicHashtableImpl() +{ +} + void BasicHashtableImpl::dispose() { if (mBuckets) { releaseBuckets(mBuckets, mBucketCount); diff --git a/libs/utils/CleanSpec.mk b/libs/utils/CleanSpec.mk new file mode 100644 index 0000000000..c3c5651b25 --- /dev/null +++ b/libs/utils/CleanSpec.mk @@ -0,0 +1,51 @@ +# Copyright (C) 2012 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. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ +$(call add-clean-step, rm -rf $(HOST_OUT)/obj/STATIC_LIBRARIES/libutils_intermediates/import_includes) +$(call add-clean-step, rm -rf $(HOST_OUT)/obj/STATIC_LIBRARIES/lib64utils_intermediates/import_includes) diff --git a/services/batteryservice/Android.mk b/services/batteryservice/Android.mk new file mode 100644 index 0000000000..0a29c36d5d --- /dev/null +++ b/services/batteryservice/Android.mk @@ -0,0 +1,17 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + BatteryProperties.cpp \ + IBatteryPropertiesListener.cpp \ + IBatteryPropertiesRegistrar.cpp + +LOCAL_STATIC_LIBRARIES := \ + libutils \ + libbinder + +LOCAL_MODULE:= libbatteryservice + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp new file mode 100644 index 0000000000..ab636a9f8b --- /dev/null +++ b/services/batteryservice/BatteryProperties.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 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 <batteryservice/BatteryService.h> +#include <binder/Parcel.h> +#include <utils/Errors.h> +#include <utils/String8.h> +#include <utils/String16.h> + +namespace android { + +/* + * Parcel read/write code must be kept in sync with + * frameworks/base/core/java/android/os/BatteryProperties.java + */ + +status_t BatteryProperties::readFromParcel(Parcel* p) { + chargerAcOnline = p->readInt32() == 1 ? true : false; + chargerUsbOnline = p->readInt32() == 1 ? true : false; + chargerWirelessOnline = p->readInt32() == 1 ? true : false; + batteryStatus = p->readInt32(); + batteryHealth = p->readInt32(); + batteryPresent = p->readInt32() == 1 ? true : false; + batteryLevel = p->readInt32(); + batteryVoltage = p->readInt32(); + batteryTemperature = p->readInt32(); + batteryTechnology = String8((p->readString16()).string()); + return OK; +} + +status_t BatteryProperties::writeToParcel(Parcel* p) const { + p->writeInt32(chargerAcOnline ? 1 : 0); + p->writeInt32(chargerUsbOnline ? 1 : 0); + p->writeInt32(chargerWirelessOnline ? 1 : 0); + p->writeInt32(batteryStatus); + p->writeInt32(batteryHealth); + p->writeInt32(batteryPresent ? 1 : 0); + p->writeInt32(batteryLevel); + p->writeInt32(batteryVoltage); + p->writeInt32(batteryTemperature); + p->writeString16(String16(batteryTechnology)); + return OK; +} + +}; // namespace android diff --git a/services/batteryservice/IBatteryPropertiesListener.cpp b/services/batteryservice/IBatteryPropertiesListener.cpp new file mode 100644 index 0000000000..19ac7f0ecd --- /dev/null +++ b/services/batteryservice/IBatteryPropertiesListener.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2013 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 <batteryservice/IBatteryPropertiesListener.h> +#include <binder/Parcel.h> + +namespace android { + +class BpBatteryPropertiesListener : public BpInterface<IBatteryPropertiesListener> +{ +public: + BpBatteryPropertiesListener(const sp<IBinder>& impl) + : BpInterface<IBatteryPropertiesListener>(impl) + { + } + + void batteryPropertiesChanged(struct BatteryProperties props) + { + Parcel data, reply; + data.writeInterfaceToken(IBatteryPropertiesListener::getInterfaceDescriptor()); + data.writeInt32(1); + props.writeToParcel(&data); + status_t err = remote()->transact(TRANSACT_BATTERYPROPERTIESCHANGED, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(BatteryPropertiesListener, "android.os.IBatteryPropertiesListener"); + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/services/batteryservice/IBatteryPropertiesRegistrar.cpp b/services/batteryservice/IBatteryPropertiesRegistrar.cpp new file mode 100644 index 0000000000..6c2d2a5bc9 --- /dev/null +++ b/services/batteryservice/IBatteryPropertiesRegistrar.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2013 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 "IBatteryPropertiesRegistrar" +//#define LOG_NDEBUG 0 +#include <utils/Log.h> + +#include <batteryservice/IBatteryPropertiesListener.h> +#include <batteryservice/IBatteryPropertiesRegistrar.h> +#include <stdint.h> +#include <sys/types.h> +#include <binder/Parcel.h> + +namespace android { + +class BpBatteryPropertiesRegistrar : public BpInterface<IBatteryPropertiesRegistrar> { +public: + BpBatteryPropertiesRegistrar(const sp<IBinder>& impl) + : BpInterface<IBatteryPropertiesRegistrar>(impl) {} + + void registerListener(const sp<IBatteryPropertiesListener>& listener) { + Parcel data; + data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor()); + data.writeStrongBinder(listener->asBinder()); + remote()->transact(REGISTER_LISTENER, data, NULL); + } + + void unregisterListener(const sp<IBatteryPropertiesListener>& listener) { + Parcel data; + data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor()); + data.writeStrongBinder(listener->asBinder()); + remote()->transact(UNREGISTER_LISTENER, data, NULL); + } +}; + +IMPLEMENT_META_INTERFACE(BatteryPropertiesRegistrar, "android.os.IBatteryPropertiesRegistrar"); + +status_t BnBatteryPropertiesRegistrar::onTransact(uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags) +{ + switch(code) { + case REGISTER_LISTENER: { + CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply); + sp<IBatteryPropertiesListener> listener = + interface_cast<IBatteryPropertiesListener>(data.readStrongBinder()); + registerListener(listener); + return OK; + } + + case UNREGISTER_LISTENER: { + CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply); + sp<IBatteryPropertiesListener> listener = + interface_cast<IBatteryPropertiesListener>(data.readStrongBinder()); + unregisterListener(listener); + return OK; + } + } + return BBinder::onTransact(code, data, reply, flags); +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/services/connectivitymanager/Android.mk b/services/connectivitymanager/Android.mk new file mode 100644 index 0000000000..e986abca21 --- /dev/null +++ b/services/connectivitymanager/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= ConnectivityManager.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libbinder + +LOCAL_MODULE:= libconnectivitymanager + +include $(BUILD_SHARED_LIBRARY) diff --git a/services/connectivitymanager/ConnectivityManager.cpp b/services/connectivitymanager/ConnectivityManager.cpp new file mode 100644 index 0000000000..949c2ac59c --- /dev/null +++ b/services/connectivitymanager/ConnectivityManager.cpp @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2013, 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 <sys/types.h> + +#include <utils/Singleton.h> + +#include <binder/BinderService.h> +#include <binder/Parcel.h> + +#include "ConnectivityManager.h" + +namespace android { + +ConnectivityManager::ConnectivityManager() { + const sp<IServiceManager> sm(defaultServiceManager()); + if (sm != NULL) { + const String16 name("connectivity"); + mConnectivityService = sm->getService(name); + } +} + +void ConnectivityManager::markSocketAsUserImpl(int fd, uid_t uid) { + Parcel data, reply; + data.writeInterfaceToken(DESCRIPTOR); + // parcelable objects are preceded by a 1 if not null in aidl generated code. + // Play nice with the generated Java + data.writeInt32(1); + data.writeFileDescriptor(fd); + data.writeInt32(uid); + mConnectivityService->transact(TRANSACTION_markSocketAsUser, data, &reply, 0); +} + +const String16 ConnectivityManager::DESCRIPTOR("android.net.IConnectivityManager"); + +ANDROID_SINGLETON_STATIC_INSTANCE(ConnectivityManager) + +}; diff --git a/services/connectivitymanager/ConnectivityManager.h b/services/connectivitymanager/ConnectivityManager.h new file mode 100644 index 0000000000..37f5d985a5 --- /dev/null +++ b/services/connectivitymanager/ConnectivityManager.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2013, 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/Singleton.h> + +namespace android { + +class ConnectivityManager : public Singleton<ConnectivityManager> { + // Keep this in sync with IConnectivityManager.aidl + static const int TRANSACTION_markSocketAsUser = IBinder::FIRST_CALL_TRANSACTION; + static const String16 DESCRIPTOR; + + friend class Singleton<ConnectivityManager>; + sp<IBinder> mConnectivityService; + + ConnectivityManager(); + + void markSocketAsUserImpl(int fd, uid_t uid); + +public: + static void markSocketAsUser(int fd, uid_t uid) { + ConnectivityManager::getInstance().markSocketAsUserImpl(fd, uid); + } +}; + +}; diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp index 815242beb1..47bab83bf7 100644 --- a/services/surfaceflinger/EventLog/EventLog.cpp +++ b/services/surfaceflinger/EventLog/EventLog.cpp @@ -31,17 +31,22 @@ ANDROID_SINGLETON_STATIC_INSTANCE(EventLog) EventLog::EventLog() { } -void EventLog::doLogJank(const String8& window, int32_t value) { - EventLog::TagBuffer buffer(LOGTAG_SF_JANK); - buffer.startList(2); +void EventLog::doLogFrameDurations(const String8& window, + const int32_t* durations, size_t numDurations) { + EventLog::TagBuffer buffer(LOGTAG_SF_FRAME_DUR); + buffer.startList(1 + numDurations); buffer.writeString8(window); - buffer.writeInt32(value); + for (size_t i = 0; i < numDurations; i++) { + buffer.writeInt32(durations[i]); + } buffer.endList(); buffer.log(); } -void EventLog::logJank(const String8& window, int32_t value) { - EventLog::getInstance().doLogJank(window, value); +void EventLog::logFrameDurations(const String8& window, + const int32_t* durations, size_t numDurations) { + EventLog::getInstance().doLogFrameDurations(window, durations, + numDurations); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/EventLog/EventLog.h b/services/surfaceflinger/EventLog/EventLog.h index 2f1cd9b3e7..52075147ef 100644 --- a/services/surfaceflinger/EventLog/EventLog.h +++ b/services/surfaceflinger/EventLog/EventLog.h @@ -30,7 +30,8 @@ class String8; class EventLog : public Singleton<EventLog> { public: - static void logJank(const String8& window, int32_t value); + static void logFrameDurations(const String8& window, + const int32_t* durations, size_t numDurations); protected: EventLog(); @@ -72,8 +73,9 @@ private: EventLog(const EventLog&); EventLog& operator =(const EventLog&); - enum { LOGTAG_SF_JANK = 60100 }; - void doLogJank(const String8& window, int32_t value); + enum { LOGTAG_SF_FRAME_DUR = 60100 }; + void doLogFrameDurations(const String8& window, const int32_t* durations, + size_t numDurations); }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/EventLog/EventLogTags.logtags b/services/surfaceflinger/EventLog/EventLogTags.logtags index c83692f447..791e0e4084 100644 --- a/services/surfaceflinger/EventLog/EventLogTags.logtags +++ b/services/surfaceflinger/EventLog/EventLogTags.logtags @@ -30,9 +30,12 @@ # 5: Id # 6: Percent # Default value for data of type int/long is 2 (bytes). +# +# See system/core/logcat/event.logtags for the master copy of the tags. + +# 60100 - 60199 reserved for surfaceflinger -# surfaceflinger -60100 sf_jank (window|3),(value|1) +60100 sf_frame_dur (window|3),(dur0|1),(dur1|1),(dur2|1),(dur3|1),(dur4|1),(dur5|1),(dur6|1) # NOTE - the range 1000000-2000000 is reserved for partners and others who # want to define their own log tags without conflicting with the core platform. diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp index 9b55d44837..d40667268b 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -17,17 +17,22 @@ // This is needed for stdint.h to define INT64_MAX in C++ #define __STDC_LIMIT_MACROS +#include <cutils/log.h> + #include <ui/Fence.h> #include <utils/String8.h> #include "FrameTracker.h" +#include "EventLog/EventLog.h" namespace android { FrameTracker::FrameTracker() : mOffset(0), - mNumFences(0) { + mNumFences(0), + mDisplayPeriod(0) { + resetFrameCountersLocked(); } void FrameTracker::setDesiredPresentTime(nsecs_t presentTime) { @@ -57,8 +62,18 @@ void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) { mNumFences++; } +void FrameTracker::setDisplayRefreshPeriod(nsecs_t displayPeriod) { + Mutex::Autolock lock(mMutex); + mDisplayPeriod = displayPeriod; +} + void FrameTracker::advanceFrame() { Mutex::Autolock lock(mMutex); + + // Update the statistic to include the frame we just finished. + updateStatsLocked(mOffset); + + // Advance to the next frame. mOffset = (mOffset+1) % NUM_FRAME_RECORDS; mFrameRecords[mOffset].desiredPresentTime = INT64_MAX; mFrameRecords[mOffset].frameReadyTime = INT64_MAX; @@ -98,12 +113,19 @@ void FrameTracker::clear() { mFrameRecords[mOffset].actualPresentTime = INT64_MAX; } +void FrameTracker::logAndResetStats(const String8& name) { + Mutex::Autolock lock(mMutex); + logStatsLocked(name); + resetFrameCountersLocked(); +} + void FrameTracker::processFencesLocked() const { FrameRecord* records = const_cast<FrameRecord*>(mFrameRecords); int& numFences = const_cast<int&>(mNumFences); for (int i = 1; i < NUM_FRAME_RECORDS && numFences > 0; i++) { size_t idx = (mOffset+NUM_FRAME_RECORDS-i) % NUM_FRAME_RECORDS; + bool updated = false; const sp<Fence>& rfence = records[idx].frameReadyFence; if (rfence != NULL) { @@ -111,6 +133,7 @@ void FrameTracker::processFencesLocked() const { if (records[idx].frameReadyTime < INT64_MAX) { records[idx].frameReadyFence = NULL; numFences--; + updated = true; } } @@ -120,11 +143,67 @@ void FrameTracker::processFencesLocked() const { if (records[idx].actualPresentTime < INT64_MAX) { records[idx].actualPresentFence = NULL; numFences--; + updated = true; + } + } + + if (updated) { + updateStatsLocked(idx); + } + } +} + +void FrameTracker::updateStatsLocked(size_t newFrameIdx) const { + int* numFrames = const_cast<int*>(mNumFrames); + + if (mDisplayPeriod > 0 && isFrameValidLocked(newFrameIdx)) { + size_t prevFrameIdx = (newFrameIdx+NUM_FRAME_RECORDS-1) % + NUM_FRAME_RECORDS; + + if (isFrameValidLocked(prevFrameIdx)) { + nsecs_t newPresentTime = + mFrameRecords[newFrameIdx].actualPresentTime; + nsecs_t prevPresentTime = + mFrameRecords[prevFrameIdx].actualPresentTime; + + nsecs_t duration = newPresentTime - prevPresentTime; + int numPeriods = int((duration + mDisplayPeriod/2) / + mDisplayPeriod); + + for (int i = 0; i < NUM_FRAME_BUCKETS-1; i++) { + int nextBucket = 1 << (i+1); + if (numPeriods < nextBucket) { + numFrames[i]++; + return; + } } + + // The last duration bucket is a catch-all. + numFrames[NUM_FRAME_BUCKETS-1]++; } } } +void FrameTracker::resetFrameCountersLocked() { + for (int i = 0; i < NUM_FRAME_BUCKETS; i++) { + mNumFrames[i] = 0; + } +} + +void FrameTracker::logStatsLocked(const String8& name) const { + for (int i = 0; i < NUM_FRAME_BUCKETS; i++) { + if (mNumFrames[i] > 0) { + EventLog::logFrameDurations(name, mNumFrames, NUM_FRAME_BUCKETS); + return; + } + } +} + +bool FrameTracker::isFrameValidLocked(size_t idx) const { + return mFrameRecords[idx].actualPresentTime > 0 && + mFrameRecords[idx].actualPresentTime < INT64_MAX; +} + void FrameTracker::dump(String8& result) const { Mutex::Autolock lock(mMutex); processFencesLocked(); diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h index 3d122c43db..92332471fd 100644 --- a/services/surfaceflinger/FrameTracker.h +++ b/services/surfaceflinger/FrameTracker.h @@ -43,6 +43,8 @@ public: // frame time history. enum { NUM_FRAME_RECORDS = 128 }; + enum { NUM_FRAME_BUCKETS = 7 }; + FrameTracker(); // setDesiredPresentTime sets the time at which the current frame @@ -68,12 +70,21 @@ public: // at which the current frame became visible to the user. void setActualPresentFence(const sp<Fence>& fence); + // setDisplayRefreshPeriod sets the display refresh period in nanoseconds. + // This is used to compute frame presentation duration statistics relative + // to this period. + void setDisplayRefreshPeriod(nsecs_t displayPeriod); + // advanceFrame advances the frame tracker to the next frame. void advanceFrame(); // clear resets all the tracked frame data to zero. void clear(); + // logAndResetStats dumps the current statistics to the binary event log + // and then resets the accumulated statistics to their initial values. + void logAndResetStats(const String8& name); + // dump appends the current frame display time history to the result string. void dump(String8& result) const; @@ -99,6 +110,21 @@ private: // change. This allows it to be called from the dump method. void processFencesLocked() const; + // updateStatsLocked updates the running statistics that are gathered + // about the frame times. + void updateStatsLocked(size_t newFrameIdx) const; + + // resetFrameCounteresLocked sets all elements of the mNumFrames array to + // 0. + void resetFrameCountersLocked(); + + // logStatsLocked dumps the current statistics to the binary event log. + void logStatsLocked(const String8& name) const; + + // isFrameValidLocked returns true if the data for the given frame index is + // valid and has all arrived (i.e. there are no oustanding fences). + bool isFrameValidLocked(size_t idx) const; + // mFrameRecords is the circular buffer storing the tracked data for each // frame. FrameRecord mFrameRecords[NUM_FRAME_RECORDS]; @@ -115,6 +141,17 @@ private: // doesn't grow with NUM_FRAME_RECORDS. int mNumFences; + // mNumFrames keeps a count of the number of frames with a duration in a + // particular range of vsync periods. Element n of the array stores the + // number of frames with duration in the half-inclusive range + // [2^n, 2^(n+1)). The last element of the array contains the count for + // all frames with duration greater than 2^(NUM_FRAME_BUCKETS-1). + int32_t mNumFrames[NUM_FRAME_BUCKETS]; + + // mDisplayPeriod is the display refresh period of the display for which + // this FrameTracker is gathering information. + nsecs_t mDisplayPeriod; + // mMutex is used to protect access to all member variables. mutable Mutex mMutex; }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 52211c22d9..7f2ce2b80d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -104,6 +104,10 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, // drawing state & current state are identical mDrawingState = mCurrentState; + + nsecs_t displayPeriod = + flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); + mFrameTracker.setDisplayRefreshPeriod(displayPeriod); } void Layer::onFirstRef() @@ -134,6 +138,7 @@ Layer::~Layer() { c->detachLayer(this); } mFlinger->deleteTextureAsync(mTextureName); + mFrameTracker.logAndResetStats(mName); } // --------------------------------------------------------------------------- @@ -1179,6 +1184,10 @@ void Layer::clearStats() { mFrameTracker.clear(); } +void Layer::logFrameStats() { + mFrameTracker.logAndResetStats(mName); +} + // --------------------------------------------------------------------------- Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 0ceb15ee39..9093116b0f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -298,6 +298,7 @@ public: void dump(String8& result, Colorizer& colorizer) const; void dumpStats(String8& result) const; void clearStats(); + void logFrameStats(); protected: // constant diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9adabe8482..cbdcd1270f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -964,6 +964,11 @@ void SurfaceFlinger::postFramebuffer() mLastSwapBufferTime = systemTime() - now; mDebugInSwapBuffers = 0; + + uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount(); + if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { + logFrameStats(); + } } void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) @@ -1972,6 +1977,10 @@ void SurfaceFlinger::onInitializeDisplays() { displays.add(d); setTransactionState(state, displays, 0); onScreenAcquired(getDefaultDisplayDevice()); + + const nsecs_t period = + getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); + mAnimFrameTracker.setDisplayRefreshPeriod(period); } void SurfaceFlinger::initializeDisplays() { @@ -2205,6 +2214,19 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde mAnimFrameTracker.clear(); } +// This should only be called from the main thread. Otherwise it would need +// the lock and should use mCurrentState rather than mDrawingState. +void SurfaceFlinger::logFrameStats() { + const LayerVector& drawingLayers = mDrawingState.layersSortedByZ; + const size_t count = drawingLayers.size(); + for (size_t i=0 ; i<count ; i++) { + const sp<Layer>& layer(drawingLayers[i]); + layer->logFrameStats(); + } + + mAnimFrameTracker.logAndResetStats(String8("<win-anim>")); +} + /*static*/ void SurfaceFlinger::appendSfConfigString(String8& result) { static const char* config = diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 21d523ba71..7099b358e2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -132,6 +132,10 @@ private: friend class Layer; friend class SurfaceTextureLayer; + // This value is specified in number of frames. Log frame stats at most + // every half hour. + enum { LOG_FRAME_STATS_PERIOD = 30*60*60 }; + // We're reference counted, never destroy SurfaceFlinger directly virtual ~SurfaceFlinger(); @@ -392,6 +396,8 @@ private: const sp<const DisplayDevice>& hw, uint32_t minLayerZ, uint32_t maxLayerZ); + void logFrameStats(); + /* ------------------------------------------------------------------------ * Attributes */ |