Loading services/surfaceflinger/Android.mk +9 −7 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ LOCAL_SRC_FILES := \ MessageQueue.cpp \ MonitoredProducer.cpp \ SurfaceFlingerConsumer.cpp \ SurfaceInterceptor.cpp \ Transform.cpp \ DisplayHardware/FramebufferSurface.cpp \ DisplayHardware/HWC2.cpp \ Loading @@ -36,11 +37,12 @@ LOCAL_SRC_FILES := \ RenderEngine/Texture.cpp \ RenderEngine/GLES10RenderEngine.cpp \ RenderEngine/GLES11RenderEngine.cpp \ RenderEngine/GLES20RenderEngine.cpp RenderEngine/GLES20RenderEngine.cpp \ LOCAL_MODULE := libsurfaceflinger LOCAL_C_INCLUDES := \ frameworks/native/vulkan/include \ external/vulkan-validation-layers/libs/vkjson external/vulkan-validation-layers/libs/vkjson \ LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES Loading Loading @@ -108,7 +110,7 @@ endif LOCAL_CFLAGS += -fvisibility=hidden -Werror=format LOCAL_CFLAGS += -std=c++14 LOCAL_STATIC_LIBRARIES := libvkjson LOCAL_STATIC_LIBRARIES := libtrace_proto libvkjson LOCAL_SHARED_LIBRARIES := \ libcutils \ liblog \ Loading @@ -122,9 +124,8 @@ LOCAL_SHARED_LIBRARIES := \ libui \ libgui \ libpowermanager \ libvulkan LOCAL_MODULE := libsurfaceflinger libvulkan \ libprotobuf-cpp-full LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code Loading Loading @@ -158,6 +159,7 @@ LOCAL_SHARED_LIBRARIES := \ libdl LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain LOCAL_STATIC_LIBRARIES := libtrace_proto LOCAL_MODULE := surfaceflinger Loading services/surfaceflinger/SurfaceInterceptor.cpp 0 → 100644 +411 −0 Original line number Diff line number Diff line /* * Copyright 2016 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. */ #undef LOG_TAG #define LOG_TAG "SurfaceInterceptor" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "Layer.h" #include "SurfaceFlinger.h" #include "SurfaceInterceptor.h" #include <cutils/log.h> #include <utils/Trace.h> #include <fstream> namespace android { // ---------------------------------------------------------------------------- void SurfaceInterceptor::enable(const SortedVector<sp<Layer>>& layers) { ATRACE_CALL(); if (mEnabled) { return; } mEnabled = true; saveExistingLayers(layers); } void SurfaceInterceptor::disable() { ATRACE_CALL(); if (!mEnabled) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); mEnabled = false; status_t err(writeProtoFileLocked()); ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied"); ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields"); mTrace.Clear(); } void SurfaceInterceptor::saveExistingLayers(const SortedVector<sp<Layer>>& layers) { ATRACE_CALL(); std::lock_guard<std::mutex> protoGuard(mTraceMutex); for (const auto& layer : layers) { saveLayerCreateLocked(layer); saveInitialLayerStateLocked(layer); } } void SurfaceInterceptor::saveInitialLayerStateLocked(const sp<const Layer>& layer) { ATRACE_CALL(); if (layer == nullptr) { return; } Increment* increment(addTraceIncrementLocked()); Transaction* transaction(increment->mutable_transaction()); transaction->set_synchronous(layer->mTransactionFlags & BnSurfaceComposer::eSynchronous); transaction->set_animation(layer->mTransactionFlags & BnSurfaceComposer::eAnimation); const int32_t layerId(getLayerId(layer)); addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(), layer->mCurrentState.active.transform.ty()); addDepthLocked(transaction, layerId, layer->mCurrentState.z); addSizeLocked(transaction, layerId, layer->mCurrentState.active.w, layer->mCurrentState.active.h); addAlphaLocked(transaction, layerId, layer->mCurrentState.alpha); addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion); addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); addCropLocked(transaction, layerId, layer->mCurrentState.crop); if (layer->mCurrentState.handle != NULL) { addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.handle, layer->mCurrentState.frameNumber); } addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop); addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags); } status_t SurfaceInterceptor::writeProtoFileLocked() { ATRACE_CALL(); std::ofstream output(mOutputFileName, std::ios::out | std::ios::trunc | std::ios::binary); // SerializeToOstream returns false when it's missing required data or when it could not write if (!mTrace.IsInitialized()) { return NOT_ENOUGH_DATA; } if (!mTrace.SerializeToOstream(&output)) { return PERMISSION_DENIED; } return NO_ERROR; } void SurfaceInterceptor::setOutputFileName(const std::string& outputFileName) { mOutputFileName = outputFileName; } const sp<const Layer> SurfaceInterceptor::getLayer(const sp<const IBinder>& handle) { const auto layerHandle(static_cast<const Layer::Handle*>(handle.get())); const sp<const Layer> layer(layerHandle->owner.promote()); // layer could be a nullptr at this point return layer; } const std::string SurfaceInterceptor::getLayerName(const sp<const Layer>& layer) { return layer->getName().string(); } int32_t SurfaceInterceptor::getLayerId(const sp<const Layer>& layer) { return layer->sequence; } Increment* SurfaceInterceptor::addTraceIncrementLocked() { Increment* increment(mTrace.add_increment()); increment->set_time_stamp(systemTime()); return increment; } Change* SurfaceInterceptor::addChangeLocked(Transaction* transaction, int32_t layerId) { Change* change(transaction->add_change()); change->set_id(layerId); return change; } void SurfaceInterceptor::setProtoRectLocked(Rectangle* protoRect, const Rect& rect) { protoRect->set_left(rect.left); protoRect->set_top(rect.top); protoRect->set_right(rect.right); protoRect->set_bottom(rect.bottom); } void SurfaceInterceptor::addPositionLocked(Transaction* transaction, int32_t layerId, float x, float y) { Change* change(addChangeLocked(transaction, layerId)); PositionChange* posChange(change->mutable_position()); posChange->set_x(x); posChange->set_y(y); } void SurfaceInterceptor::addDepthLocked(Transaction* transaction, int32_t layerId, uint32_t z) { Change* change(addChangeLocked(transaction, layerId)); LayerChange* depthChange(change->mutable_layer()); depthChange->set_layer(z); } void SurfaceInterceptor::addSizeLocked(Transaction* transaction, int32_t layerId, uint32_t w, uint32_t h) { Change* change(addChangeLocked(transaction, layerId)); SizeChange* sizeChange(change->mutable_size()); sizeChange->set_w(w); sizeChange->set_h(h); } void SurfaceInterceptor::addAlphaLocked(Transaction* transaction, int32_t layerId, float alpha) { Change* change(addChangeLocked(transaction, layerId)); AlphaChange* alphaChange(change->mutable_alpha()); alphaChange->set_alpha(alpha); } void SurfaceInterceptor::addMatrixLocked(Transaction* transaction, int32_t layerId, const layer_state_t::matrix22_t& matrix) { Change* change(addChangeLocked(transaction, layerId)); MatrixChange* matrixChange(change->mutable_matrix()); matrixChange->set_dsdx(matrix.dsdx); matrixChange->set_dtdx(matrix.dtdx); matrixChange->set_dsdy(matrix.dsdy); matrixChange->set_dtdy(matrix.dtdy); } void SurfaceInterceptor::addTransparentRegionLocked(Transaction* transaction, int32_t layerId, const Region& transRegion) { Change* change(addChangeLocked(transaction, layerId)); TransparentRegionHintChange* transparentChange(change->mutable_transparent_region_hint()); for (const auto& rect : transRegion) { Rectangle* protoRect(transparentChange->add_region()); setProtoRectLocked(protoRect, rect); } } void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags) { // There can be multiple flags changed if (flags & layer_state_t::eLayerHidden) { Change* change(addChangeLocked(transaction, layerId)); HiddenFlagChange* flagChange(change->mutable_hidden_flag()); flagChange->set_hidden_flag(true); } if (flags & layer_state_t::eLayerOpaque) { Change* change(addChangeLocked(transaction, layerId)); OpaqueFlagChange* flagChange(change->mutable_opaque_flag()); flagChange->set_opaque_flag(true); } if (flags & layer_state_t::eLayerSecure) { Change* change(addChangeLocked(transaction, layerId)); SecureFlagChange* flagChange(change->mutable_secure_flag()); flagChange->set_secure_flag(true); } } void SurfaceInterceptor::addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack) { Change* change(addChangeLocked(transaction, layerId)); LayerStackChange* layerStackChange(change->mutable_layer_stack()); layerStackChange->set_layer_stack(layerStack); } void SurfaceInterceptor::addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect) { Change* change(addChangeLocked(transaction, layerId)); CropChange* cropChange(change->mutable_crop()); Rectangle* protoRect(cropChange->mutable_rectangle()); setProtoRectLocked(protoRect, rect); } void SurfaceInterceptor::addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect) { Change* change(addChangeLocked(transaction, layerId)); FinalCropChange* finalCropChange(change->mutable_final_crop()); Rectangle* protoRect(finalCropChange->mutable_rectangle()); setProtoRectLocked(protoRect, rect); } void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp<const IBinder>& handle, uint64_t frameNumber) { Change* change(addChangeLocked(transaction, layerId)); const sp<const Layer> layer(getLayer(handle)); if (layer == nullptr) { ALOGE("An existing layer could not be retrieved with the handle" " for the deferred transaction"); return; } DeferredTransactionChange* deferTransaction(change->mutable_deferred_transaction()); deferTransaction->set_layer_id(getLayerId(layer)); deferTransaction->set_frame_number(frameNumber); } void SurfaceInterceptor::addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, int32_t overrideScalingMode) { Change* change(addChangeLocked(transaction, layerId)); OverrideScalingModeChange* overrideChange(change->mutable_override_scaling_mode()); overrideChange->set_override_scaling_mode(overrideScalingMode); } void SurfaceInterceptor::addChangedPropertiesLocked(Transaction* transaction, const layer_state_t& state) { const sp<const Layer> layer(getLayer(state.surface)); if (layer == nullptr) { ALOGE("An existing layer could not be retrieved with the surface " "from the layer_state_t surface in the update transaction"); return; } const int32_t layerId(getLayerId(layer)); if (state.what & layer_state_t::ePositionChanged) { addPositionLocked(transaction, layerId, state.x, state.y); } if (state.what & layer_state_t::eLayerChanged) { addDepthLocked(transaction, layerId, state.z); } if (state.what & layer_state_t::eSizeChanged) { addSizeLocked(transaction, layerId, state.w, state.h); } if (state.what & layer_state_t::eAlphaChanged) { addAlphaLocked(transaction, layerId, state.alpha); } if (state.what & layer_state_t::eMatrixChanged) { addMatrixLocked(transaction, layerId, state.matrix); } if (state.what & layer_state_t::eTransparentRegionChanged) { addTransparentRegionLocked(transaction, layerId, state.transparentRegion); } if (state.what & layer_state_t::eFlagsChanged) { addFlagsLocked(transaction, layerId, state.flags); } if (state.what & layer_state_t::eLayerStackChanged) { addLayerStackLocked(transaction, layerId, state.layerStack); } if (state.what & layer_state_t::eCropChanged) { addCropLocked(transaction, layerId, state.crop); } if (state.what & layer_state_t::eDeferTransaction) { addDeferTransactionLocked(transaction, layerId, state.handle, state.frameNumber); } if (state.what & layer_state_t::eFinalCropChanged) { addFinalCropLocked(transaction, layerId, state.finalCrop); } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); } } void SurfaceInterceptor::addUpdatedLayersLocked(Increment* increment, uint32_t flags, const Vector<ComposerState>& stateUpdates) { Transaction* transaction(increment->mutable_transaction()); transaction->set_synchronous(flags & BnSurfaceComposer::eSynchronous); transaction->set_animation(flags & BnSurfaceComposer::eAnimation); for (const auto& compState: stateUpdates) { addChangedPropertiesLocked(transaction, compState.state); } } void SurfaceInterceptor::addCreatedLayerLocked(Increment* increment, const sp<const Layer>& layer) { Create* create(increment->mutable_create()); create->set_id(getLayerId(layer)); create->set_name(getLayerName(layer)); create->set_w(layer->mCurrentState.active.w); create->set_h(layer->mCurrentState.active.h); } void SurfaceInterceptor::addDeletedLayerLocked(Increment* increment, const sp<const Layer>& layer) { Delete* deleteLayer(increment->mutable_delete_()); deleteLayer->set_id(getLayerId(layer)); } void SurfaceInterceptor::addUpdatedBufferLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width, uint32_t height, uint64_t frameNumber) { BufferUpdate* update(increment->mutable_buffer_update()); update->set_id(getLayerId(layer)); update->set_w(width); update->set_h(height); update->set_frame_number(frameNumber); } void SurfaceInterceptor::addUpdatedVsyncLocked(Increment* increment, nsecs_t timestamp) { VSyncEvent* event(increment->mutable_vsync_event()); event->set_when(timestamp); } void SurfaceInterceptor::saveLayerUpdates(const Vector<ComposerState>& stateUpdates, uint32_t flags) { ATRACE_CALL(); if (!mEnabled || stateUpdates.size() <= 0) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addUpdatedLayersLocked(addTraceIncrementLocked(), flags, stateUpdates); } void SurfaceInterceptor::saveLayerCreate(const sp<const Layer>& layer) { ATRACE_CALL(); if (!mEnabled || layer == nullptr) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addCreatedLayerLocked(addTraceIncrementLocked(), layer); } void SurfaceInterceptor::saveLayerCreateLocked(const sp<const Layer>& layer) { if (!mEnabled || layer == nullptr) { return; } addCreatedLayerLocked(addTraceIncrementLocked(), layer); } void SurfaceInterceptor::saveLayerDelete(const sp<const Layer>& layer) { ATRACE_CALL(); if (!mEnabled || layer == nullptr) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addDeletedLayerLocked(addTraceIncrementLocked(), layer); } void SurfaceInterceptor::saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height, uint64_t frameNumber) { ATRACE_CALL(); if (!mEnabled || layer == nullptr) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addUpdatedBufferLocked(addTraceIncrementLocked(), layer, width, height, frameNumber); } void SurfaceInterceptor::saveVSyncEvent(nsecs_t timestamp) { if (!mEnabled) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addUpdatedVsyncLocked(addTraceIncrementLocked(), timestamp); } } // namespace android services/surfaceflinger/SurfaceInterceptor.h 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Copyright 2016 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_SURFACEINTERCEPTOR_H #define ANDROID_SURFACEINTERCEPTOR_H #include <frameworks/native/cmds/surfacecapturereplay/proto/src/trace.pb.h> #include <mutex> namespace android { class BufferItem; class Layer; struct layer_state_t; constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat"; /* * SurfaceInterceptor intercepts and stores incoming streams of window * properties on SurfaceFlinger. */ class SurfaceInterceptor { public: // The layer vector is used to capture the inital snapshot in the trace void enable(const SortedVector<sp<Layer>>& layers); void disable(); void setOutputFileName(const std::string& OutputFileName); void saveLayerUpdates(const Vector<ComposerState>& state, uint32_t flags); void saveLayerCreate(const sp<const Layer>& layer); void saveLayerDelete(const sp<const Layer>& layer); void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height, uint64_t frameNumber); void saveVSyncEvent(nsecs_t timestamp); private: void saveExistingLayers(const SortedVector<sp<Layer>>& layers); void saveInitialLayerStateLocked(const sp<const Layer>& layer); void saveLayerCreateLocked(const sp<const Layer>& layer); status_t writeProtoFileLocked(); const sp<const Layer> getLayer(const sp<const IBinder>& handle); const std::string getLayerName(const sp<const Layer>& layer); int32_t getLayerId(const sp<const Layer>& layer); Increment* addTraceIncrementLocked(); void addUpdatedLayersLocked(Increment* increment, uint32_t flags, const Vector<ComposerState>& stateUpdates); void addCreatedLayerLocked(Increment* increment, const sp<const Layer>& layer); void addDeletedLayerLocked(Increment* increment, const sp<const Layer>& layer); void addUpdatedBufferLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width, uint32_t height, uint64_t frameNumber); void addUpdatedVsyncLocked(Increment* increment, nsecs_t timestamp); Change* addChangeLocked(Transaction* transaction, int32_t layerId); void setProtoRectLocked(Rectangle* protoRect, const Rect& rect); void addPositionLocked(Transaction* transaction, int32_t layerId, float x, float y); void addDepthLocked(Transaction* transaction, int32_t layerId, uint32_t z); void addSizeLocked(Transaction* transaction, int32_t layerId, uint32_t w, uint32_t h); void addAlphaLocked(Transaction* transaction, int32_t layerId, float alpha); void addMatrixLocked(Transaction* transaction, int32_t layerId, const layer_state_t::matrix22_t& matrix); void addTransparentRegionLocked(Transaction* transaction, int32_t layerId, const Region& transRegion); void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags); void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack); void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp<const IBinder>& handle, uint64_t frameNumber); void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, int32_t overrideScalingMode); void addChangedPropertiesLocked(Transaction* transaction, const layer_state_t& state); bool mEnabled {false}; std::string mOutputFileName {DEFAULT_FILENAME}; std::mutex mTraceMutex {}; Trace mTrace {}; }; } #endif // ANDROID_SURFACEINTERCEPTOR_H services/surfaceflinger/tests/Android.mk +15 −7 Original line number Diff line number Diff line Loading @@ -3,12 +3,15 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_CFLAGS := -std=c++14 LOCAL_MODULE := SurfaceFlinger_test LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := \ Transaction_test.cpp \ SurfaceInterceptor_test.cpp LOCAL_SHARED_LIBRARIES := \ libEGL \ Loading @@ -16,9 +19,14 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libcutils \ libgui \ libprotobuf-cpp-full \ libui \ libutils \ LOCAL_STATIC_LIBRARIES := libtrace_proto LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code # Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) # to integrate with auto-test framework. include $(BUILD_NATIVE_TEST) Loading Loading
services/surfaceflinger/Android.mk +9 −7 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ LOCAL_SRC_FILES := \ MessageQueue.cpp \ MonitoredProducer.cpp \ SurfaceFlingerConsumer.cpp \ SurfaceInterceptor.cpp \ Transform.cpp \ DisplayHardware/FramebufferSurface.cpp \ DisplayHardware/HWC2.cpp \ Loading @@ -36,11 +37,12 @@ LOCAL_SRC_FILES := \ RenderEngine/Texture.cpp \ RenderEngine/GLES10RenderEngine.cpp \ RenderEngine/GLES11RenderEngine.cpp \ RenderEngine/GLES20RenderEngine.cpp RenderEngine/GLES20RenderEngine.cpp \ LOCAL_MODULE := libsurfaceflinger LOCAL_C_INCLUDES := \ frameworks/native/vulkan/include \ external/vulkan-validation-layers/libs/vkjson external/vulkan-validation-layers/libs/vkjson \ LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES Loading Loading @@ -108,7 +110,7 @@ endif LOCAL_CFLAGS += -fvisibility=hidden -Werror=format LOCAL_CFLAGS += -std=c++14 LOCAL_STATIC_LIBRARIES := libvkjson LOCAL_STATIC_LIBRARIES := libtrace_proto libvkjson LOCAL_SHARED_LIBRARIES := \ libcutils \ liblog \ Loading @@ -122,9 +124,8 @@ LOCAL_SHARED_LIBRARIES := \ libui \ libgui \ libpowermanager \ libvulkan LOCAL_MODULE := libsurfaceflinger libvulkan \ libprotobuf-cpp-full LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code Loading Loading @@ -158,6 +159,7 @@ LOCAL_SHARED_LIBRARIES := \ libdl LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain LOCAL_STATIC_LIBRARIES := libtrace_proto LOCAL_MODULE := surfaceflinger Loading
services/surfaceflinger/SurfaceInterceptor.cpp 0 → 100644 +411 −0 Original line number Diff line number Diff line /* * Copyright 2016 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. */ #undef LOG_TAG #define LOG_TAG "SurfaceInterceptor" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "Layer.h" #include "SurfaceFlinger.h" #include "SurfaceInterceptor.h" #include <cutils/log.h> #include <utils/Trace.h> #include <fstream> namespace android { // ---------------------------------------------------------------------------- void SurfaceInterceptor::enable(const SortedVector<sp<Layer>>& layers) { ATRACE_CALL(); if (mEnabled) { return; } mEnabled = true; saveExistingLayers(layers); } void SurfaceInterceptor::disable() { ATRACE_CALL(); if (!mEnabled) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); mEnabled = false; status_t err(writeProtoFileLocked()); ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied"); ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields"); mTrace.Clear(); } void SurfaceInterceptor::saveExistingLayers(const SortedVector<sp<Layer>>& layers) { ATRACE_CALL(); std::lock_guard<std::mutex> protoGuard(mTraceMutex); for (const auto& layer : layers) { saveLayerCreateLocked(layer); saveInitialLayerStateLocked(layer); } } void SurfaceInterceptor::saveInitialLayerStateLocked(const sp<const Layer>& layer) { ATRACE_CALL(); if (layer == nullptr) { return; } Increment* increment(addTraceIncrementLocked()); Transaction* transaction(increment->mutable_transaction()); transaction->set_synchronous(layer->mTransactionFlags & BnSurfaceComposer::eSynchronous); transaction->set_animation(layer->mTransactionFlags & BnSurfaceComposer::eAnimation); const int32_t layerId(getLayerId(layer)); addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(), layer->mCurrentState.active.transform.ty()); addDepthLocked(transaction, layerId, layer->mCurrentState.z); addSizeLocked(transaction, layerId, layer->mCurrentState.active.w, layer->mCurrentState.active.h); addAlphaLocked(transaction, layerId, layer->mCurrentState.alpha); addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion); addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); addCropLocked(transaction, layerId, layer->mCurrentState.crop); if (layer->mCurrentState.handle != NULL) { addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.handle, layer->mCurrentState.frameNumber); } addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop); addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags); } status_t SurfaceInterceptor::writeProtoFileLocked() { ATRACE_CALL(); std::ofstream output(mOutputFileName, std::ios::out | std::ios::trunc | std::ios::binary); // SerializeToOstream returns false when it's missing required data or when it could not write if (!mTrace.IsInitialized()) { return NOT_ENOUGH_DATA; } if (!mTrace.SerializeToOstream(&output)) { return PERMISSION_DENIED; } return NO_ERROR; } void SurfaceInterceptor::setOutputFileName(const std::string& outputFileName) { mOutputFileName = outputFileName; } const sp<const Layer> SurfaceInterceptor::getLayer(const sp<const IBinder>& handle) { const auto layerHandle(static_cast<const Layer::Handle*>(handle.get())); const sp<const Layer> layer(layerHandle->owner.promote()); // layer could be a nullptr at this point return layer; } const std::string SurfaceInterceptor::getLayerName(const sp<const Layer>& layer) { return layer->getName().string(); } int32_t SurfaceInterceptor::getLayerId(const sp<const Layer>& layer) { return layer->sequence; } Increment* SurfaceInterceptor::addTraceIncrementLocked() { Increment* increment(mTrace.add_increment()); increment->set_time_stamp(systemTime()); return increment; } Change* SurfaceInterceptor::addChangeLocked(Transaction* transaction, int32_t layerId) { Change* change(transaction->add_change()); change->set_id(layerId); return change; } void SurfaceInterceptor::setProtoRectLocked(Rectangle* protoRect, const Rect& rect) { protoRect->set_left(rect.left); protoRect->set_top(rect.top); protoRect->set_right(rect.right); protoRect->set_bottom(rect.bottom); } void SurfaceInterceptor::addPositionLocked(Transaction* transaction, int32_t layerId, float x, float y) { Change* change(addChangeLocked(transaction, layerId)); PositionChange* posChange(change->mutable_position()); posChange->set_x(x); posChange->set_y(y); } void SurfaceInterceptor::addDepthLocked(Transaction* transaction, int32_t layerId, uint32_t z) { Change* change(addChangeLocked(transaction, layerId)); LayerChange* depthChange(change->mutable_layer()); depthChange->set_layer(z); } void SurfaceInterceptor::addSizeLocked(Transaction* transaction, int32_t layerId, uint32_t w, uint32_t h) { Change* change(addChangeLocked(transaction, layerId)); SizeChange* sizeChange(change->mutable_size()); sizeChange->set_w(w); sizeChange->set_h(h); } void SurfaceInterceptor::addAlphaLocked(Transaction* transaction, int32_t layerId, float alpha) { Change* change(addChangeLocked(transaction, layerId)); AlphaChange* alphaChange(change->mutable_alpha()); alphaChange->set_alpha(alpha); } void SurfaceInterceptor::addMatrixLocked(Transaction* transaction, int32_t layerId, const layer_state_t::matrix22_t& matrix) { Change* change(addChangeLocked(transaction, layerId)); MatrixChange* matrixChange(change->mutable_matrix()); matrixChange->set_dsdx(matrix.dsdx); matrixChange->set_dtdx(matrix.dtdx); matrixChange->set_dsdy(matrix.dsdy); matrixChange->set_dtdy(matrix.dtdy); } void SurfaceInterceptor::addTransparentRegionLocked(Transaction* transaction, int32_t layerId, const Region& transRegion) { Change* change(addChangeLocked(transaction, layerId)); TransparentRegionHintChange* transparentChange(change->mutable_transparent_region_hint()); for (const auto& rect : transRegion) { Rectangle* protoRect(transparentChange->add_region()); setProtoRectLocked(protoRect, rect); } } void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags) { // There can be multiple flags changed if (flags & layer_state_t::eLayerHidden) { Change* change(addChangeLocked(transaction, layerId)); HiddenFlagChange* flagChange(change->mutable_hidden_flag()); flagChange->set_hidden_flag(true); } if (flags & layer_state_t::eLayerOpaque) { Change* change(addChangeLocked(transaction, layerId)); OpaqueFlagChange* flagChange(change->mutable_opaque_flag()); flagChange->set_opaque_flag(true); } if (flags & layer_state_t::eLayerSecure) { Change* change(addChangeLocked(transaction, layerId)); SecureFlagChange* flagChange(change->mutable_secure_flag()); flagChange->set_secure_flag(true); } } void SurfaceInterceptor::addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack) { Change* change(addChangeLocked(transaction, layerId)); LayerStackChange* layerStackChange(change->mutable_layer_stack()); layerStackChange->set_layer_stack(layerStack); } void SurfaceInterceptor::addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect) { Change* change(addChangeLocked(transaction, layerId)); CropChange* cropChange(change->mutable_crop()); Rectangle* protoRect(cropChange->mutable_rectangle()); setProtoRectLocked(protoRect, rect); } void SurfaceInterceptor::addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect) { Change* change(addChangeLocked(transaction, layerId)); FinalCropChange* finalCropChange(change->mutable_final_crop()); Rectangle* protoRect(finalCropChange->mutable_rectangle()); setProtoRectLocked(protoRect, rect); } void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp<const IBinder>& handle, uint64_t frameNumber) { Change* change(addChangeLocked(transaction, layerId)); const sp<const Layer> layer(getLayer(handle)); if (layer == nullptr) { ALOGE("An existing layer could not be retrieved with the handle" " for the deferred transaction"); return; } DeferredTransactionChange* deferTransaction(change->mutable_deferred_transaction()); deferTransaction->set_layer_id(getLayerId(layer)); deferTransaction->set_frame_number(frameNumber); } void SurfaceInterceptor::addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, int32_t overrideScalingMode) { Change* change(addChangeLocked(transaction, layerId)); OverrideScalingModeChange* overrideChange(change->mutable_override_scaling_mode()); overrideChange->set_override_scaling_mode(overrideScalingMode); } void SurfaceInterceptor::addChangedPropertiesLocked(Transaction* transaction, const layer_state_t& state) { const sp<const Layer> layer(getLayer(state.surface)); if (layer == nullptr) { ALOGE("An existing layer could not be retrieved with the surface " "from the layer_state_t surface in the update transaction"); return; } const int32_t layerId(getLayerId(layer)); if (state.what & layer_state_t::ePositionChanged) { addPositionLocked(transaction, layerId, state.x, state.y); } if (state.what & layer_state_t::eLayerChanged) { addDepthLocked(transaction, layerId, state.z); } if (state.what & layer_state_t::eSizeChanged) { addSizeLocked(transaction, layerId, state.w, state.h); } if (state.what & layer_state_t::eAlphaChanged) { addAlphaLocked(transaction, layerId, state.alpha); } if (state.what & layer_state_t::eMatrixChanged) { addMatrixLocked(transaction, layerId, state.matrix); } if (state.what & layer_state_t::eTransparentRegionChanged) { addTransparentRegionLocked(transaction, layerId, state.transparentRegion); } if (state.what & layer_state_t::eFlagsChanged) { addFlagsLocked(transaction, layerId, state.flags); } if (state.what & layer_state_t::eLayerStackChanged) { addLayerStackLocked(transaction, layerId, state.layerStack); } if (state.what & layer_state_t::eCropChanged) { addCropLocked(transaction, layerId, state.crop); } if (state.what & layer_state_t::eDeferTransaction) { addDeferTransactionLocked(transaction, layerId, state.handle, state.frameNumber); } if (state.what & layer_state_t::eFinalCropChanged) { addFinalCropLocked(transaction, layerId, state.finalCrop); } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); } } void SurfaceInterceptor::addUpdatedLayersLocked(Increment* increment, uint32_t flags, const Vector<ComposerState>& stateUpdates) { Transaction* transaction(increment->mutable_transaction()); transaction->set_synchronous(flags & BnSurfaceComposer::eSynchronous); transaction->set_animation(flags & BnSurfaceComposer::eAnimation); for (const auto& compState: stateUpdates) { addChangedPropertiesLocked(transaction, compState.state); } } void SurfaceInterceptor::addCreatedLayerLocked(Increment* increment, const sp<const Layer>& layer) { Create* create(increment->mutable_create()); create->set_id(getLayerId(layer)); create->set_name(getLayerName(layer)); create->set_w(layer->mCurrentState.active.w); create->set_h(layer->mCurrentState.active.h); } void SurfaceInterceptor::addDeletedLayerLocked(Increment* increment, const sp<const Layer>& layer) { Delete* deleteLayer(increment->mutable_delete_()); deleteLayer->set_id(getLayerId(layer)); } void SurfaceInterceptor::addUpdatedBufferLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width, uint32_t height, uint64_t frameNumber) { BufferUpdate* update(increment->mutable_buffer_update()); update->set_id(getLayerId(layer)); update->set_w(width); update->set_h(height); update->set_frame_number(frameNumber); } void SurfaceInterceptor::addUpdatedVsyncLocked(Increment* increment, nsecs_t timestamp) { VSyncEvent* event(increment->mutable_vsync_event()); event->set_when(timestamp); } void SurfaceInterceptor::saveLayerUpdates(const Vector<ComposerState>& stateUpdates, uint32_t flags) { ATRACE_CALL(); if (!mEnabled || stateUpdates.size() <= 0) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addUpdatedLayersLocked(addTraceIncrementLocked(), flags, stateUpdates); } void SurfaceInterceptor::saveLayerCreate(const sp<const Layer>& layer) { ATRACE_CALL(); if (!mEnabled || layer == nullptr) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addCreatedLayerLocked(addTraceIncrementLocked(), layer); } void SurfaceInterceptor::saveLayerCreateLocked(const sp<const Layer>& layer) { if (!mEnabled || layer == nullptr) { return; } addCreatedLayerLocked(addTraceIncrementLocked(), layer); } void SurfaceInterceptor::saveLayerDelete(const sp<const Layer>& layer) { ATRACE_CALL(); if (!mEnabled || layer == nullptr) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addDeletedLayerLocked(addTraceIncrementLocked(), layer); } void SurfaceInterceptor::saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height, uint64_t frameNumber) { ATRACE_CALL(); if (!mEnabled || layer == nullptr) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addUpdatedBufferLocked(addTraceIncrementLocked(), layer, width, height, frameNumber); } void SurfaceInterceptor::saveVSyncEvent(nsecs_t timestamp) { if (!mEnabled) { return; } std::lock_guard<std::mutex> protoGuard(mTraceMutex); addUpdatedVsyncLocked(addTraceIncrementLocked(), timestamp); } } // namespace android
services/surfaceflinger/SurfaceInterceptor.h 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Copyright 2016 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_SURFACEINTERCEPTOR_H #define ANDROID_SURFACEINTERCEPTOR_H #include <frameworks/native/cmds/surfacecapturereplay/proto/src/trace.pb.h> #include <mutex> namespace android { class BufferItem; class Layer; struct layer_state_t; constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat"; /* * SurfaceInterceptor intercepts and stores incoming streams of window * properties on SurfaceFlinger. */ class SurfaceInterceptor { public: // The layer vector is used to capture the inital snapshot in the trace void enable(const SortedVector<sp<Layer>>& layers); void disable(); void setOutputFileName(const std::string& OutputFileName); void saveLayerUpdates(const Vector<ComposerState>& state, uint32_t flags); void saveLayerCreate(const sp<const Layer>& layer); void saveLayerDelete(const sp<const Layer>& layer); void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height, uint64_t frameNumber); void saveVSyncEvent(nsecs_t timestamp); private: void saveExistingLayers(const SortedVector<sp<Layer>>& layers); void saveInitialLayerStateLocked(const sp<const Layer>& layer); void saveLayerCreateLocked(const sp<const Layer>& layer); status_t writeProtoFileLocked(); const sp<const Layer> getLayer(const sp<const IBinder>& handle); const std::string getLayerName(const sp<const Layer>& layer); int32_t getLayerId(const sp<const Layer>& layer); Increment* addTraceIncrementLocked(); void addUpdatedLayersLocked(Increment* increment, uint32_t flags, const Vector<ComposerState>& stateUpdates); void addCreatedLayerLocked(Increment* increment, const sp<const Layer>& layer); void addDeletedLayerLocked(Increment* increment, const sp<const Layer>& layer); void addUpdatedBufferLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width, uint32_t height, uint64_t frameNumber); void addUpdatedVsyncLocked(Increment* increment, nsecs_t timestamp); Change* addChangeLocked(Transaction* transaction, int32_t layerId); void setProtoRectLocked(Rectangle* protoRect, const Rect& rect); void addPositionLocked(Transaction* transaction, int32_t layerId, float x, float y); void addDepthLocked(Transaction* transaction, int32_t layerId, uint32_t z); void addSizeLocked(Transaction* transaction, int32_t layerId, uint32_t w, uint32_t h); void addAlphaLocked(Transaction* transaction, int32_t layerId, float alpha); void addMatrixLocked(Transaction* transaction, int32_t layerId, const layer_state_t::matrix22_t& matrix); void addTransparentRegionLocked(Transaction* transaction, int32_t layerId, const Region& transRegion); void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags); void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack); void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp<const IBinder>& handle, uint64_t frameNumber); void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, int32_t overrideScalingMode); void addChangedPropertiesLocked(Transaction* transaction, const layer_state_t& state); bool mEnabled {false}; std::string mOutputFileName {DEFAULT_FILENAME}; std::mutex mTraceMutex {}; Trace mTrace {}; }; } #endif // ANDROID_SURFACEINTERCEPTOR_H
services/surfaceflinger/tests/Android.mk +15 −7 Original line number Diff line number Diff line Loading @@ -3,12 +3,15 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_CFLAGS := -std=c++14 LOCAL_MODULE := SurfaceFlinger_test LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := \ Transaction_test.cpp \ SurfaceInterceptor_test.cpp LOCAL_SHARED_LIBRARIES := \ libEGL \ Loading @@ -16,9 +19,14 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libcutils \ libgui \ libprotobuf-cpp-full \ libui \ libutils \ LOCAL_STATIC_LIBRARIES := libtrace_proto LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code # Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) # to integrate with auto-test framework. include $(BUILD_NATIVE_TEST) Loading