diff options
author | 2021-12-16 14:33:46 -0800 | |
---|---|---|
committer | 2022-02-20 01:24:53 -0800 | |
commit | f502922b5a4869c399bebd2254039183b58c8a7d (patch) | |
tree | 4e628ab16b081af4cff25896a1e6783b852af2a3 | |
parent | c255951aaa56aef738bc50799aaaf8ba6012e54b (diff) |
Migrate screenshot methods to AIDL
Additonal service, named as "SurfaceFlingerAIDL", is added to surfaceflinger during the process of migrating ISurfaceComposer interface to AIDL. New changes are put into namespace, android::gui. Once migration is complete, this service will be deleted.
This CL migrates Screenshot methods to AIDL, more will come.
Bug: 211037638
Test: screencap
Change-Id: Idee91fa2444646639735847b1c76e983af39227f
21 files changed, 455 insertions, 225 deletions
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 75c5e26fb0..5ab0abc561 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -46,9 +46,11 @@ using namespace aidl::android::hardware::graphics; namespace android { +using gui::DisplayCaptureArgs; using gui::IDisplayEventConnection; using gui::IRegionSamplingListener; using gui::IWindowInfosListener; +using gui::LayerCaptureArgs; using ui::ColorMode; class BpSurfaceComposer : public BpInterface<ISurfaceComposer> @@ -118,36 +120,6 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - status_t captureDisplay(const DisplayCaptureArgs& args, - const sp<IScreenCaptureListener>& captureListener) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(args.write, data); - SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(captureListener)); - - return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply); - } - - status_t captureDisplay(DisplayId displayId, - const sp<IScreenCaptureListener>& captureListener) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(data.writeUint64, displayId.value); - SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(captureListener)); - - return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply); - } - - status_t captureLayers(const LayerCaptureArgs& args, - const sp<IScreenCaptureListener>& captureListener) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(args.write, data); - SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(captureListener)); - - return remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); - } - bool authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) const override { Parcel data, reply; @@ -1451,36 +1423,6 @@ status_t BnSurfaceComposer::onTransact( bootFinished(); return NO_ERROR; } - case CAPTURE_DISPLAY: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - DisplayCaptureArgs args; - sp<IScreenCaptureListener> captureListener; - SAFE_PARCEL(args.read, data); - SAFE_PARCEL(data.readStrongBinder, &captureListener); - - return captureDisplay(args, captureListener); - } - case CAPTURE_DISPLAY_BY_ID: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - uint64_t value; - SAFE_PARCEL(data.readUint64, &value); - const auto id = DisplayId::fromValue(value); - if (!id) return BAD_VALUE; - - sp<IScreenCaptureListener> captureListener; - SAFE_PARCEL(data.readStrongBinder, &captureListener); - - return captureDisplay(*id, captureListener); - } - case CAPTURE_LAYERS: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - LayerCaptureArgs args; - sp<IScreenCaptureListener> captureListener; - SAFE_PARCEL(args.read, data); - SAFE_PARCEL(data.readStrongBinder, &captureListener); - - return captureLayers(args, captureListener); - } case AUTHENTICATE_SURFACE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IGraphicBufferProducer> bufferProducer = diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 9022e7d5a4..6944d38dfe 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -686,85 +686,89 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, int8_t changeFrame // ---------------------------------------------------------------------------- -status_t CaptureArgs::write(Parcel& output) const { - SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(pixelFormat)); - SAFE_PARCEL(output.write, sourceCrop); - SAFE_PARCEL(output.writeFloat, frameScaleX); - SAFE_PARCEL(output.writeFloat, frameScaleY); - SAFE_PARCEL(output.writeBool, captureSecureLayers); - SAFE_PARCEL(output.writeInt32, uid); - SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(dataspace)); - SAFE_PARCEL(output.writeBool, allowProtected); - SAFE_PARCEL(output.writeBool, grayscale); +namespace gui { + +status_t CaptureArgs::writeToParcel(Parcel* output) const { + SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(pixelFormat)); + SAFE_PARCEL(output->write, sourceCrop); + SAFE_PARCEL(output->writeFloat, frameScaleX); + SAFE_PARCEL(output->writeFloat, frameScaleY); + SAFE_PARCEL(output->writeBool, captureSecureLayers); + SAFE_PARCEL(output->writeInt32, uid); + SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(dataspace)); + SAFE_PARCEL(output->writeBool, allowProtected); + SAFE_PARCEL(output->writeBool, grayscale); return NO_ERROR; } -status_t CaptureArgs::read(const Parcel& input) { +status_t CaptureArgs::readFromParcel(const Parcel* input) { int32_t value = 0; - SAFE_PARCEL(input.readInt32, &value); + SAFE_PARCEL(input->readInt32, &value); pixelFormat = static_cast<ui::PixelFormat>(value); - SAFE_PARCEL(input.read, sourceCrop); - SAFE_PARCEL(input.readFloat, &frameScaleX); - SAFE_PARCEL(input.readFloat, &frameScaleY); - SAFE_PARCEL(input.readBool, &captureSecureLayers); - SAFE_PARCEL(input.readInt32, &uid); - SAFE_PARCEL(input.readInt32, &value); + SAFE_PARCEL(input->read, sourceCrop); + SAFE_PARCEL(input->readFloat, &frameScaleX); + SAFE_PARCEL(input->readFloat, &frameScaleY); + SAFE_PARCEL(input->readBool, &captureSecureLayers); + SAFE_PARCEL(input->readInt32, &uid); + SAFE_PARCEL(input->readInt32, &value); dataspace = static_cast<ui::Dataspace>(value); - SAFE_PARCEL(input.readBool, &allowProtected); - SAFE_PARCEL(input.readBool, &grayscale); + SAFE_PARCEL(input->readBool, &allowProtected); + SAFE_PARCEL(input->readBool, &grayscale); return NO_ERROR; } -status_t DisplayCaptureArgs::write(Parcel& output) const { - SAFE_PARCEL(CaptureArgs::write, output); +status_t DisplayCaptureArgs::writeToParcel(Parcel* output) const { + SAFE_PARCEL(CaptureArgs::writeToParcel, output); - SAFE_PARCEL(output.writeStrongBinder, displayToken); - SAFE_PARCEL(output.writeUint32, width); - SAFE_PARCEL(output.writeUint32, height); - SAFE_PARCEL(output.writeBool, useIdentityTransform); + SAFE_PARCEL(output->writeStrongBinder, displayToken); + SAFE_PARCEL(output->writeUint32, width); + SAFE_PARCEL(output->writeUint32, height); + SAFE_PARCEL(output->writeBool, useIdentityTransform); return NO_ERROR; } -status_t DisplayCaptureArgs::read(const Parcel& input) { - SAFE_PARCEL(CaptureArgs::read, input); +status_t DisplayCaptureArgs::readFromParcel(const Parcel* input) { + SAFE_PARCEL(CaptureArgs::readFromParcel, input); - SAFE_PARCEL(input.readStrongBinder, &displayToken); - SAFE_PARCEL(input.readUint32, &width); - SAFE_PARCEL(input.readUint32, &height); - SAFE_PARCEL(input.readBool, &useIdentityTransform); + SAFE_PARCEL(input->readStrongBinder, &displayToken); + SAFE_PARCEL(input->readUint32, &width); + SAFE_PARCEL(input->readUint32, &height); + SAFE_PARCEL(input->readBool, &useIdentityTransform); return NO_ERROR; } -status_t LayerCaptureArgs::write(Parcel& output) const { - SAFE_PARCEL(CaptureArgs::write, output); +status_t LayerCaptureArgs::writeToParcel(Parcel* output) const { + SAFE_PARCEL(CaptureArgs::writeToParcel, output); - SAFE_PARCEL(output.writeStrongBinder, layerHandle); - SAFE_PARCEL(output.writeInt32, excludeHandles.size()); + SAFE_PARCEL(output->writeStrongBinder, layerHandle); + SAFE_PARCEL(output->writeInt32, excludeHandles.size()); for (auto el : excludeHandles) { - SAFE_PARCEL(output.writeStrongBinder, el); + SAFE_PARCEL(output->writeStrongBinder, el); } - SAFE_PARCEL(output.writeBool, childrenOnly); + SAFE_PARCEL(output->writeBool, childrenOnly); return NO_ERROR; } -status_t LayerCaptureArgs::read(const Parcel& input) { - SAFE_PARCEL(CaptureArgs::read, input); +status_t LayerCaptureArgs::readFromParcel(const Parcel* input) { + SAFE_PARCEL(CaptureArgs::readFromParcel, input); - SAFE_PARCEL(input.readStrongBinder, &layerHandle); + SAFE_PARCEL(input->readStrongBinder, &layerHandle); int32_t numExcludeHandles = 0; - SAFE_PARCEL_READ_SIZE(input.readInt32, &numExcludeHandles, input.dataSize()); + SAFE_PARCEL_READ_SIZE(input->readInt32, &numExcludeHandles, input->dataSize()); excludeHandles.reserve(numExcludeHandles); for (int i = 0; i < numExcludeHandles; i++) { sp<IBinder> binder; - SAFE_PARCEL(input.readStrongBinder, &binder); + SAFE_PARCEL(input->readStrongBinder, &binder); excludeHandles.emplace(binder); } - SAFE_PARCEL(input.readBool, &childrenOnly); + SAFE_PARCEL(input->readBool, &childrenOnly); return NO_ERROR; } +}; // namespace gui + ReleaseCallbackId BufferData::generateReleaseCallbackId() const { return {buffer->getId(), frameNumber}; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 9269c3e5a7..26ccda580a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -46,6 +46,7 @@ #include <ui/DynamicDisplayInfo.h> #include <private/gui/ComposerService.h> +#include <private/gui/ComposerServiceAIDL.h> // This server size should always be smaller than the server cache size #define BUFFER_CACHE_MAX_SIZE 64 @@ -62,6 +63,7 @@ using ui::ColorMode; // --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService); +ANDROID_SINGLETON_STATIC_INSTANCE(ComposerServiceAIDL); namespace { // Initialize transaction id counter used to generate transaction ids @@ -120,6 +122,52 @@ void ComposerService::composerServiceDied() mDeathObserver = nullptr; } +ComposerServiceAIDL::ComposerServiceAIDL() : Singleton<ComposerServiceAIDL>() { + std::scoped_lock lock(mMutex); + connectLocked(); +} + +bool ComposerServiceAIDL::connectLocked() { + const String16 name("SurfaceFlingerAIDL"); + mComposerService = waitForService<gui::ISurfaceComposer>(name); + if (mComposerService == nullptr) { + return false; // fatal error or permission problem + } + + // Create the death listener. + class DeathObserver : public IBinder::DeathRecipient { + ComposerServiceAIDL& mComposerService; + virtual void binderDied(const wp<IBinder>& who) { + ALOGW("ComposerService aidl remote (surfaceflinger) died [%p]", who.unsafe_get()); + mComposerService.composerServiceDied(); + } + + public: + explicit DeathObserver(ComposerServiceAIDL& mgr) : mComposerService(mgr) {} + }; + + mDeathObserver = new DeathObserver(*const_cast<ComposerServiceAIDL*>(this)); + IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver); + return true; +} + +/*static*/ sp<gui::ISurfaceComposer> ComposerServiceAIDL::getComposerService() { + ComposerServiceAIDL& instance = ComposerServiceAIDL::getInstance(); + std::scoped_lock lock(instance.mMutex); + if (instance.mComposerService == nullptr) { + if (ComposerServiceAIDL::getInstance().connectLocked()) { + ALOGD("ComposerServiceAIDL reconnected"); + } + } + return instance.mComposerService; +} + +void ComposerServiceAIDL::composerServiceDied() { + std::scoped_lock lock(mMutex); + mComposerService = nullptr; + mDeathObserver = nullptr; +} + class DefaultComposerClient: public Singleton<DefaultComposerClient> { Mutex mLock; sp<SurfaceComposerClient> mClient; @@ -2267,26 +2315,29 @@ status_t SurfaceComposerClient::removeWindowInfosListener( status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs, const sp<IScreenCaptureListener>& captureListener) { - sp<ISurfaceComposer> s(ComposerService::getComposerService()); + sp<gui::ISurfaceComposer> s(ComposerServiceAIDL::getComposerService()); if (s == nullptr) return NO_INIT; - return s->captureDisplay(captureArgs, captureListener); + binder::Status status = s->captureDisplay(captureArgs, captureListener); + return status.transactionError(); } status_t ScreenshotClient::captureDisplay(DisplayId displayId, const sp<IScreenCaptureListener>& captureListener) { - sp<ISurfaceComposer> s(ComposerService::getComposerService()); + sp<gui::ISurfaceComposer> s(ComposerServiceAIDL::getComposerService()); if (s == nullptr) return NO_INIT; - return s->captureDisplay(displayId, captureListener); + binder::Status status = s->captureDisplayById(displayId.value, captureListener); + return status.transactionError(); } status_t ScreenshotClient::captureLayers(const LayerCaptureArgs& captureArgs, const sp<IScreenCaptureListener>& captureListener) { - sp<ISurfaceComposer> s(ComposerService::getComposerService()); + sp<gui::ISurfaceComposer> s(ComposerServiceAIDL::getComposerService()); if (s == nullptr) return NO_INIT; - return s->captureLayers(captureArgs, captureListener); + binder::Status status = s->captureLayers(captureArgs, captureListener); + return status.transactionError(); } // --------------------------------------------------------------------------------- diff --git a/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl b/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl new file mode 100644 index 0000000000..2caa2b9f61 --- /dev/null +++ b/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2021 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. + */ + +package android.gui; + +parcelable DisplayCaptureArgs cpp_header "gui/DisplayCaptureArgs.h"; diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl new file mode 100644 index 0000000000..07921a59a5 --- /dev/null +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -0,0 +1,42 @@ +/* + * Copyright 2021 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. + */ + +package android.gui; + +import android.gui.DisplayCaptureArgs; +import android.gui.LayerCaptureArgs; +import android.gui.IScreenCaptureListener; + +/** @hide */ +interface ISurfaceComposer { + /** + * Capture the specified screen. This requires READ_FRAME_BUFFER + * permission. This function will fail if there is a secure window on + * screen and DisplayCaptureArgs.captureSecureLayers is false. + * + * This function can capture a subregion (the source crop) of the screen. + * The subregion can be optionally rotated. It will also be scaled to + * match the size of the output buffer. + */ + void captureDisplay(in DisplayCaptureArgs args, IScreenCaptureListener listener); + void captureDisplayById(long displayId, IScreenCaptureListener listener); + /** + * Capture a subtree of the layer hierarchy, potentially ignoring the root node. + * This requires READ_FRAME_BUFFER permission. This function will fail if there + * is a secure window on screen + */ + void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener); +} diff --git a/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl b/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl new file mode 100644 index 0000000000..f0def5019a --- /dev/null +++ b/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2021 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. + */ + +package android.gui; + +parcelable LayerCaptureArgs cpp_header "gui/LayerCaptureArgs.h"; diff --git a/libs/gui/include/gui/DisplayCaptureArgs.h b/libs/gui/include/gui/DisplayCaptureArgs.h new file mode 100644 index 0000000000..ec884cfa8c --- /dev/null +++ b/libs/gui/include/gui/DisplayCaptureArgs.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 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. + */ + +#pragma once + +#include <stdint.h> +#include <sys/types.h> + +#include <binder/IBinder.h> +#include <binder/Parcel.h> +#include <binder/Parcelable.h> +#include <ui/GraphicTypes.h> +#include <ui/PixelFormat.h> + +namespace android::gui { + +struct CaptureArgs : public Parcelable { + const static int32_t UNSET_UID = -1; + virtual ~CaptureArgs() = default; + + ui::PixelFormat pixelFormat{ui::PixelFormat::RGBA_8888}; + Rect sourceCrop; + float frameScaleX{1}; + float frameScaleY{1}; + bool captureSecureLayers{false}; + int32_t uid{UNSET_UID}; + // Force capture to be in a color space. If the value is ui::Dataspace::UNKNOWN, the captured + // result will be in the display's colorspace. + // The display may use non-RGB dataspace (ex. displayP3) that could cause pixel data could be + // different from SRGB (byte per color), and failed when checking colors in tests. + // NOTE: In normal cases, we want the screen to be captured in display's colorspace. + ui::Dataspace dataspace = ui::Dataspace::UNKNOWN; + + // The receiver of the capture can handle protected buffer. A protected buffer has + // GRALLOC_USAGE_PROTECTED usage bit and must not be accessed unprotected behaviour. + // Any read/write access from unprotected context will result in undefined behaviour. + // Protected contents are typically DRM contents. This has no direct implication to the + // secure property of the surface, which is specified by the application explicitly to avoid + // the contents being accessed/captured by screenshot or unsecure display. + bool allowProtected = false; + + bool grayscale = false; + + virtual status_t writeToParcel(Parcel* output) const; + virtual status_t readFromParcel(const Parcel* input); +}; + +struct DisplayCaptureArgs : CaptureArgs { + sp<IBinder> displayToken; + uint32_t width{0}; + uint32_t height{0}; + bool useIdentityTransform{false}; + + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; +}; + +}; // namespace android::gui diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 0a59f52fcd..4dfc383b57 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -58,11 +58,9 @@ namespace android { struct client_cache_t; struct ComposerState; -struct DisplayCaptureArgs; struct DisplayStatInfo; struct DisplayState; struct InputWindowCommands; -struct LayerCaptureArgs; class LayerDebugInfo; class HdrCapabilities; class IGraphicBufferProducer; @@ -75,6 +73,13 @@ using gui::IRegionSamplingListener; using gui::IScreenCaptureListener; using gui::SpHash; +namespace gui { + +struct DisplayCaptureArgs; +struct LayerCaptureArgs; + +} // namespace gui + namespace ui { struct DisplayMode; @@ -261,27 +266,6 @@ public: */ virtual void setGameContentType(const sp<IBinder>& display, bool on) = 0; - /** - * Capture the specified screen. This requires READ_FRAME_BUFFER - * permission. This function will fail if there is a secure window on - * screen and DisplayCaptureArgs.captureSecureLayers is false. - * - * This function can capture a subregion (the source crop) of the screen. - * The subregion can be optionally rotated. It will also be scaled to - * match the size of the output buffer. - */ - virtual status_t captureDisplay(const DisplayCaptureArgs&, - const sp<IScreenCaptureListener>&) = 0; - - virtual status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&) = 0; - - /** - * Capture a subtree of the layer hierarchy, potentially ignoring the root node. - * This requires READ_FRAME_BUFFER permission. This function will fail if there - * is a secure window on screen - */ - virtual status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&) = 0; - /* Clears the frame statistics for animations. * * Requires the ACCESS_SURFACE_FLINGER permission. @@ -621,8 +605,8 @@ public: GET_DISPLAY_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. GET_ACTIVE_DISPLAY_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. GET_DISPLAY_STATE, - CAPTURE_DISPLAY, - CAPTURE_LAYERS, + CAPTURE_DISPLAY, // Deprecated. Autogenerated by .aidl now. + CAPTURE_LAYERS, // Deprecated. Autogenerated by .aidl now. CLEAR_ANIMATION_FRAME_STATS, GET_ANIMATION_FRAME_STATS, SET_POWER_MODE, @@ -649,7 +633,7 @@ public: GET_DESIRED_DISPLAY_MODE_SPECS, GET_DISPLAY_BRIGHTNESS_SUPPORT, SET_DISPLAY_BRIGHTNESS, - CAPTURE_DISPLAY_BY_ID, + CAPTURE_DISPLAY_BY_ID, // Deprecated. Autogenerated by .aidl now. NOTIFY_POWER_BOOST, SET_GLOBAL_SHADOW_SETTINGS, GET_AUTO_LOW_LATENCY_MODE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. diff --git a/libs/gui/include/gui/LayerCaptureArgs.h b/libs/gui/include/gui/LayerCaptureArgs.h new file mode 100644 index 0000000000..05ff9d5b7b --- /dev/null +++ b/libs/gui/include/gui/LayerCaptureArgs.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 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. + */ + +#pragma once + +#include <stdint.h> +#include <sys/types.h> + +#include <gui/DisplayCaptureArgs.h> +#include <gui/SpHash.h> +#include <unordered_set> + +namespace android::gui { + +struct LayerCaptureArgs : CaptureArgs { + sp<IBinder> layerHandle; + std::unordered_set<sp<IBinder>, SpHash<IBinder>> excludeHandles; + bool childrenOnly{false}; + + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; +}; + +}; // namespace android::gui diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index f7206193cd..7a36fdaaec 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -29,7 +29,9 @@ #include <android/gui/DropInputMode.h> #include <android/gui/FocusRequest.h> +#include <gui/DisplayCaptureArgs.h> #include <gui/ISurfaceComposer.h> +#include <gui/LayerCaptureArgs.h> #include <gui/LayerMetadata.h> #include <gui/SpHash.h> #include <gui/SurfaceControl.h> @@ -370,56 +372,6 @@ static inline int compare_type(const DisplayState& lhs, const DisplayState& rhs) bool ValidateFrameRate(float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy, const char* functionName, bool privileged = false); -struct CaptureArgs { - const static int32_t UNSET_UID = -1; - virtual ~CaptureArgs() = default; - - ui::PixelFormat pixelFormat{ui::PixelFormat::RGBA_8888}; - Rect sourceCrop; - float frameScaleX{1}; - float frameScaleY{1}; - bool captureSecureLayers{false}; - int32_t uid{UNSET_UID}; - // Force capture to be in a color space. If the value is ui::Dataspace::UNKNOWN, the captured - // result will be in the display's colorspace. - // The display may use non-RGB dataspace (ex. displayP3) that could cause pixel data could be - // different from SRGB (byte per color), and failed when checking colors in tests. - // NOTE: In normal cases, we want the screen to be captured in display's colorspace. - ui::Dataspace dataspace = ui::Dataspace::UNKNOWN; - - // The receiver of the capture can handle protected buffer. A protected buffer has - // GRALLOC_USAGE_PROTECTED usage bit and must not be accessed unprotected behaviour. - // Any read/write access from unprotected context will result in undefined behaviour. - // Protected contents are typically DRM contents. This has no direct implication to the - // secure property of the surface, which is specified by the application explicitly to avoid - // the contents being accessed/captured by screenshot or unsecure display. - bool allowProtected = false; - - bool grayscale = false; - - virtual status_t write(Parcel& output) const; - virtual status_t read(const Parcel& input); -}; - -struct DisplayCaptureArgs : CaptureArgs { - sp<IBinder> displayToken; - uint32_t width{0}; - uint32_t height{0}; - bool useIdentityTransform{false}; - - status_t write(Parcel& output) const override; - status_t read(const Parcel& input) override; -}; - -struct LayerCaptureArgs : CaptureArgs { - sp<IBinder> layerHandle; - std::unordered_set<sp<IBinder>, SpHash<IBinder>> excludeHandles; - bool childrenOnly{false}; - - status_t write(Parcel& output) const override; - status_t read(const Parcel& input) override; -}; - }; // namespace android #endif // ANDROID_SF_LAYER_STATE_H diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 25637efce2..6c79b5bbbc 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -57,7 +57,9 @@ class IGraphicBufferProducer; class ITunnelModeEnabledListener; class Region; +using gui::DisplayCaptureArgs; using gui::IRegionSamplingListener; +using gui::LayerCaptureArgs; struct SurfaceControlStats { SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t latchTime, diff --git a/libs/gui/include/private/gui/ComposerService.h b/libs/gui/include/private/gui/ComposerService.h index fa1071a4e3..05ed0a0576 100644 --- a/libs/gui/include/private/gui/ComposerService.h +++ b/libs/gui/include/private/gui/ComposerService.h @@ -37,7 +37,7 @@ class ISurfaceComposer; // Users of this class should not retain the value from // getComposerService() for an extended period. // -// (It's not clear that using Singleton is useful here anymore.) +// (TODO: b/219785927, It's not clear that using Singleton is useful here anymore.) class ComposerService : public Singleton<ComposerService> { sp<ISurfaceComposer> mComposerService; diff --git a/libs/gui/include/private/gui/ComposerServiceAIDL.h b/libs/gui/include/private/gui/ComposerServiceAIDL.h new file mode 100644 index 0000000000..fee37eefe0 --- /dev/null +++ b/libs/gui/include/private/gui/ComposerServiceAIDL.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 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. + */ + +#pragma once + +#include <stdint.h> +#include <sys/types.h> + +#include <android/gui/ISurfaceComposer.h> + +#include <utils/Singleton.h> +#include <utils/StrongPointer.h> + +namespace android { + +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- + +// This holds our connection to the composer service (i.e. SurfaceFlinger). +// If the remote side goes away, we will re-establish the connection. +// Users of this class should not retain the value from +// getComposerService() for an extended period. +// +// (TODO: b/219785927, It's not clear that using Singleton is useful here anymore.) +class ComposerServiceAIDL : public Singleton<ComposerServiceAIDL> { + sp<gui::ISurfaceComposer> mComposerService; + sp<IBinder::DeathRecipient> mDeathObserver; + mutable std::mutex mMutex; + + ComposerServiceAIDL(); + bool connectLocked(); + void composerServiceDied(); + friend class Singleton<ComposerServiceAIDL>; + +public: + // Get a connection to the Composer Service. This will block until + // a connection is established. Returns null if permission is denied. + static sp<gui::ISurfaceComposer> getComposerService(); +}; + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 42a32f3b42..179bdd76aa 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -29,6 +29,7 @@ #include <gui/SyncScreenCaptureListener.h> #include <gui/test/CallbackUtils.h> #include <private/gui/ComposerService.h> +#include <private/gui/ComposerServiceAIDL.h> #include <ui/DisplayMode.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicTypes.h> @@ -283,13 +284,13 @@ protected: static status_t captureDisplay(DisplayCaptureArgs& captureArgs, ScreenCaptureResults& captureResults) { - const auto sf = ComposerService::getComposerService(); + const auto sf = ComposerServiceAIDL::getComposerService(); SurfaceComposerClient::Transaction().apply(true); const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener(); - status_t status = sf->captureDisplay(captureArgs, captureListener); - if (status != NO_ERROR) { - return status; + binder::Status status = sf->captureDisplay(captureArgs, captureListener); + if (status.transactionError() != NO_ERROR) { + return status.transactionError(); } captureResults = captureListener->waitForResults(); return captureResults.result; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 605628096d..a885e926a3 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -31,6 +31,7 @@ #include <gui/SyncScreenCaptureListener.h> #include <inttypes.h> #include <private/gui/ComposerService.h> +#include <private/gui/ComposerServiceAIDL.h> #include <sys/types.h> #include <ui/BufferQueueDefs.h> #include <ui/DisplayMode.h> @@ -205,13 +206,13 @@ protected: static status_t captureDisplay(DisplayCaptureArgs& captureArgs, ScreenCaptureResults& captureResults) { - const auto sf = ComposerService::getComposerService(); + const auto sf = ComposerServiceAIDL::getComposerService(); SurfaceComposerClient::Transaction().apply(true); const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener(); - status_t status = sf->captureDisplay(captureArgs, captureListener); - if (status != NO_ERROR) { - return status; + binder::Status status = sf->captureDisplay(captureArgs, captureListener); + if (status.transactionError() != NO_ERROR) { + return status.transactionError(); } captureResults = captureListener->waitForResults(); return captureResults.result; @@ -766,16 +767,6 @@ public: void setAutoLowLatencyMode(const sp<IBinder>& /*display*/, bool /*on*/) override {} void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {} - status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&) override { - return NO_ERROR; - } - status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&) override { - return NO_ERROR; - } - status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&) override { - return NO_ERROR; - } - status_t clearAnimationFrameStats() override { return NO_ERROR; } status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override { return NO_ERROR; diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index d9958f31c5..000a2cb0d3 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -76,6 +76,7 @@ cc_defaults { "libaidlcommonsupport", "libcompositionengine", "libframetimeline", + "libgui_aidl_static", "libperfetto_client_experimental", "librenderengine", "libscheduler", diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 59c07b6db1..1227edf7a2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5472,9 +5472,6 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case SET_FRAME_RATE: case GET_DISPLAY_BRIGHTNESS_SUPPORT: case GET_DISPLAY_DECORATION_SUPPORT: - // captureLayers and captureDisplay will handle the permission check in the function - case CAPTURE_LAYERS: - case CAPTURE_DISPLAY: case SET_FRAME_TIMELINE_INFO: case GET_GPU_CONTEXT_PRIORITY: case GET_MAX_ACQUIRED_BUFFER_COUNT: { @@ -5509,8 +5506,7 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { } return OK; } - case ADD_TRANSACTION_TRACE_LISTENER: - case CAPTURE_DISPLAY_BY_ID: { + case ADD_TRANSACTION_TRACE_LISTENER: { IPCThreadState* ipc = IPCThreadState::self(); const int uid = ipc->getCallingUid(); if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) { @@ -5540,6 +5536,11 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { } return PERMISSION_DENIED; } + case CAPTURE_LAYERS: + case CAPTURE_DISPLAY: + case CAPTURE_DISPLAY_BY_ID: + LOG_FATAL("Deprecated opcode: %d", code); + return PERMISSION_DENIED; } // These codes are used for the IBinder protocol to either interrogate the recipient @@ -7188,6 +7189,34 @@ bool SurfaceFlinger::commitCreatedLayers() { mLayersAdded = true; return true; } + +// gui::ISurfaceComposer +binder::Status SurfaceComposerAIDL::captureDisplay( + const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) { + status_t status = mFlinger->captureDisplay(args, captureListener); + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::captureDisplayById( + int64_t displayId, const sp<IScreenCaptureListener>& captureListener) { + status_t status; + IPCThreadState* ipc = IPCThreadState::self(); + const int uid = ipc->getCallingUid(); + if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) { + std::optional<DisplayId> id = DisplayId::fromValue(static_cast<uint64_t>(displayId)); + status = mFlinger->captureDisplay(*id, captureListener); + } else { + status = PERMISSION_DENIED; + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::captureLayers( + const LayerCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) { + status_t status = mFlinger->captureLayers(args, captureListener); + return binder::Status::fromStatusT(status); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 3ecce33d33..f09ee5fad0 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -23,6 +23,7 @@ */ #include <android-base/thread_annotations.h> +#include <android/gui/BnSurfaceComposer.h> #include <cutils/atomic.h> #include <cutils/compiler.h> #include <gui/BufferQueue.h> @@ -106,9 +107,13 @@ class RegionSamplingThread; class RenderArea; class TimeStats; class FrameTracer; +class ScreenCapturer; class WindowInfosListenerInvoker; +using gui::CaptureArgs; +using gui::DisplayCaptureArgs; using gui::IRegionSamplingListener; +using gui::LayerCaptureArgs; using gui::ScreenCaptureResults; namespace frametimeline { @@ -540,9 +545,9 @@ private: ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) override; - status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&) override; - status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&) override; - status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&) override; + status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&); + status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&); + status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&); status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override; status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*) @@ -1401,6 +1406,22 @@ private: } mPowerHintSessionData GUARDED_BY(SF_MAIN_THREAD); nsecs_t mAnimationTransactionTimeout = s2ns(5); + + friend class SurfaceComposerAIDL; +}; + +class SurfaceComposerAIDL : public gui::BnSurfaceComposer { +public: + SurfaceComposerAIDL(sp<SurfaceFlinger> sf) { mFlinger = sf; } + + binder::Status captureDisplay(const DisplayCaptureArgs&, + const sp<IScreenCaptureListener>&) override; + binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override; + binder::Status captureLayers(const LayerCaptureArgs&, + const sp<IScreenCaptureListener>&) override; + +private: + sp<SurfaceFlinger> mFlinger; }; } // namespace android diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index caeff4ab21..ec180548e1 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -152,6 +152,11 @@ int main(int, char**) { sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO); + // publish gui::ISurfaceComposer, the new AIDL interface + sp<SurfaceComposerAIDL> composerAIDL = new SurfaceComposerAIDL(flinger); + sm->addService(String16("SurfaceFlingerAIDL"), composerAIDL, false, + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO); + startDisplayService(); // dependency on SF getting registered above if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) { diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp index fa1a5ed6b0..094b0ffc0f 100644 --- a/services/surfaceflinger/tests/LayerState_test.cpp +++ b/services/surfaceflinger/tests/LayerState_test.cpp @@ -22,6 +22,8 @@ #include <gui/LayerState.h> namespace android { +using gui::DisplayCaptureArgs; +using gui::LayerCaptureArgs; using gui::ScreenCaptureResults; namespace test { @@ -40,11 +42,11 @@ TEST(LayerStateTest, ParcellingDisplayCaptureArgs) { args.grayscale = true; Parcel p; - args.write(p); + args.writeToParcel(&p); p.setDataPosition(0); DisplayCaptureArgs args2; - args2.read(p); + args2.readFromParcel(&p); ASSERT_EQ(args.pixelFormat, args2.pixelFormat); ASSERT_EQ(args.sourceCrop, args2.sourceCrop); @@ -71,11 +73,11 @@ TEST(LayerStateTest, ParcellingLayerCaptureArgs) { args.grayscale = true; Parcel p; - args.write(p); + args.writeToParcel(&p); p.setDataPosition(0); LayerCaptureArgs args2; - args2.read(p); + args2.readFromParcel(&p); ASSERT_EQ(args.pixelFormat, args2.pixelFormat); ASSERT_EQ(args.sourceCrop, args2.sourceCrop); diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h index cae76849bf..ee7e92cbf6 100644 --- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h +++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h @@ -16,6 +16,7 @@ #pragma once #include <gui/SyncScreenCaptureListener.h> +#include <private/gui/ComposerServiceAIDL.h> #include <ui/Rect.h> #include <utils/String8.h> #include <functional> @@ -31,15 +32,15 @@ class ScreenCapture : public RefBase { public: static status_t captureDisplay(DisplayCaptureArgs& captureArgs, ScreenCaptureResults& captureResults) { - const auto sf = ComposerService::getComposerService(); + const auto sf = ComposerServiceAIDL::getComposerService(); SurfaceComposerClient::Transaction().apply(true); captureArgs.dataspace = ui::Dataspace::V0_SRGB; const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener(); - status_t status = sf->captureDisplay(captureArgs, captureListener); + binder::Status status = sf->captureDisplay(captureArgs, captureListener); - if (status != NO_ERROR) { - return status; + if (status.transactionError() != NO_ERROR) { + return status.transactionError(); } captureResults = captureListener->waitForResults(); return captureResults.result; @@ -64,14 +65,14 @@ public: static status_t captureLayers(LayerCaptureArgs& captureArgs, ScreenCaptureResults& captureResults) { - const auto sf = ComposerService::getComposerService(); + const auto sf = ComposerServiceAIDL::getComposerService(); SurfaceComposerClient::Transaction().apply(true); captureArgs.dataspace = ui::Dataspace::V0_SRGB; const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener(); - status_t status = sf->captureLayers(captureArgs, captureListener); - if (status != NO_ERROR) { - return status; + binder::Status status = sf->captureLayers(captureArgs, captureListener); + if (status.transactionError() != NO_ERROR) { + return status.transactionError(); } captureResults = captureListener->waitForResults(); return captureResults.result; |