diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 742fc8393..3ffc67e69 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -39,6 +39,7 @@ namespace android { class ComposerState; class DisplayState; class DisplayInfo; +class DisplayStatInfo; class IDisplayEventConnection; class IMemoryHeap; class Rect; @@ -122,6 +123,12 @@ public: virtual status_t getDisplayConfigs(const sp& display, Vector* configs) = 0; + /* returns display statistics for a given display + * intended to be used by the media framework to properly schedule + * video frames */ + virtual status_t getDisplayStats(const sp& display, + DisplayStatInfo* stats) = 0; + /* indicates which of the configurations returned by getDisplayInfo is * currently active */ virtual int getActiveConfig(const sp& display) = 0; @@ -177,6 +184,7 @@ public: CLEAR_ANIMATION_FRAME_STATS, GET_ANIMATION_FRAME_STATS, SET_POWER_MODE, + GET_DISPLAY_STATS, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/include/ui/DisplayStatInfo.h b/include/ui/DisplayStatInfo.h new file mode 100644 index 000000000..0549a832b --- /dev/null +++ b/include/ui/DisplayStatInfo.h @@ -0,0 +1,31 @@ +/* + * Copyright 2014 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_UI_DISPLAY_STAT_INFO_H +#define ANDROID_UI_DISPLAY_STAT_INFO_H + +#include + +namespace android { + +struct DisplayStatInfo { + nsecs_t vsyncTime; + nsecs_t vsyncPeriod; +}; + +}; // namespace android + +#endif // ANDROID_COMPOSER_DISPLAY_STAT_INFO_H diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 4d65c5647..81e83360f 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -33,6 +33,7 @@ #include #include +#include #include @@ -237,6 +238,22 @@ public: return result; } + virtual status_t getDisplayStats(const sp& display, + DisplayStatInfo* stats) + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); + remote()->transact(BnSurfaceComposer::GET_DISPLAY_STATS, data, &reply); + status_t result = reply.readInt32(); + if (result == NO_ERROR) { + memcpy(stats, + reply.readInplace(sizeof(DisplayStatInfo)), + sizeof(DisplayStatInfo)); + } + return result; + } + virtual int getActiveConfig(const sp& display) { Parcel data, reply; @@ -390,6 +407,18 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } + case GET_DISPLAY_STATS: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + DisplayStatInfo stats; + sp display = data.readStrongBinder(); + status_t result = getDisplayStats(display, &stats); + reply->writeInt32(result); + if (result == NO_ERROR) { + memcpy(reply->writeInplace(sizeof(DisplayStatInfo)), + &stats, sizeof(DisplayStatInfo)); + } + return NO_ERROR; + } case GET_ACTIVE_CONFIG: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 12da9a5cb..3738a5548 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -408,6 +408,12 @@ void DispSync::setPeriod(nsecs_t period) { mThread->updateModel(mPeriod, mPhase); } +nsecs_t DispSync::getPeriod() { + // lock mutex as mPeriod changes multiple times in updateModelLocked + Mutex::Autolock lock(mMutex); + return mPeriod; +} + void DispSync::updateModelLocked() { if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) { nsecs_t durationSum = 0; diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index 7a26df33f..96efc3491 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -101,6 +101,9 @@ public: // turned on. It should NOT be used after that. void setPeriod(nsecs_t period); + // The getPeriod method returns the current vsync period. + nsecs_t getPeriod(); + // setRefreshSkipCount specifies an additional number of refresh // cycles to skip. For example, on a 60Hz display, a skip count of 1 // will result in events happening at 30Hz. Default is zero. The idea diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 043b07558..12f22a7a8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -603,6 +604,19 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, return NO_ERROR; } +status_t SurfaceFlinger::getDisplayStats(const sp& display, + DisplayStatInfo* stats) { + if (stats == NULL) { + return BAD_VALUE; + } + + // FIXME for now we always return stats for the primary display + memset(stats, 0, sizeof(*stats)); + stats->vsyncTime = mPrimaryDispSync.computeNextRefresh(0); + stats->vsyncPeriod = mPrimaryDispSync.getPeriod(); + return NO_ERROR; +} + int SurfaceFlinger::getActiveConfig(const sp& display) { return getDisplayDevice(display)->getActiveConfig(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 26f0acfa3..2cc522b1a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -206,6 +206,8 @@ private: Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation); + virtual status_t getDisplayStats(const sp& display, + DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp& display, Vector* configs); virtual int getActiveConfig(const sp& display);