123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- #include <algorithm>
- #include <functional>
- #include <limits>
- #include <ostream>
- #include <gtest/gtest.h>
- #include <gui/ISurfaceComposer.h>
- #include <gui/LayerDebugInfo.h>
- #include <gui/Surface.h>
- #include <gui/SurfaceComposerClient.h>
- #include <private/android_filesystem_config.h>
- #include <private/gui/ComposerService.h>
- #include <ui/DisplayInfo.h>
- #include <utils/String8.h>
- namespace android {
- using Transaction = SurfaceComposerClient::Transaction;
- using ui::ColorMode;
- namespace {
- const String8 DISPLAY_NAME("Credentials Display Test");
- const String8 SURFACE_NAME("Test Surface Name");
- const uint32_t ROTATION = 0;
- const float FRAME_SCALE = 1.0f;
- } // namespace
- /**
- * This class tests the CheckCredentials method in SurfaceFlinger.
- * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
- * return anything meaningful.
- */
- class CredentialsTest : public ::testing::Test {
- protected:
- void SetUp() override {
- // Start the tests as root.
- seteuid(AID_ROOT);
- ASSERT_NO_FATAL_FAILURE(initClient());
- }
- void TearDown() override {
- mComposerClient->dispose();
- mBGSurfaceControl.clear();
- mComposerClient.clear();
- // Finish the tests as root.
- seteuid(AID_ROOT);
- }
- sp<IBinder> mDisplay;
- sp<IBinder> mVirtualDisplay;
- sp<SurfaceComposerClient> mComposerClient;
- sp<SurfaceControl> mBGSurfaceControl;
- sp<SurfaceControl> mVirtualSurfaceControl;
- void initClient() {
- mComposerClient = new SurfaceComposerClient;
- ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
- }
- void setupBackgroundSurface() {
- mDisplay = SurfaceComposerClient::getInternalDisplayToken();
- ASSERT_FALSE(mDisplay == nullptr);
- DisplayInfo info;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
- const ssize_t displayWidth = info.w;
- const ssize_t displayHeight = info.h;
- // Background surface
- mBGSurfaceControl =
- mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
- PIXEL_FORMAT_RGBA_8888, 0);
- ASSERT_TRUE(mBGSurfaceControl != nullptr);
- ASSERT_TRUE(mBGSurfaceControl->isValid());
- Transaction t;
- t.setDisplayLayerStack(mDisplay, 0);
- ASSERT_EQ(NO_ERROR,
- t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
- }
- void setupVirtualDisplay() {
- mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
- const ssize_t displayWidth = 100;
- const ssize_t displayHeight = 100;
- // Background surface
- mVirtualSurfaceControl =
- mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
- PIXEL_FORMAT_RGBA_8888, 0);
- ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
- ASSERT_TRUE(mVirtualSurfaceControl->isValid());
- Transaction t;
- t.setDisplayLayerStack(mVirtualDisplay, 0);
- ASSERT_EQ(NO_ERROR,
- t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
- .show(mVirtualSurfaceControl)
- .apply());
- }
- /**
- * Sets UID to imitate Graphic's process.
- */
- void setGraphicsUID() {
- seteuid(AID_ROOT);
- seteuid(AID_GRAPHICS);
- }
- /**
- * Sets UID to imitate System's process.
- */
- void setSystemUID() {
- seteuid(AID_ROOT);
- seteuid(AID_SYSTEM);
- }
- /**
- * Sets UID to imitate a process that doesn't have any special privileges in
- * our code.
- */
- void setBinUID() {
- seteuid(AID_ROOT);
- seteuid(AID_BIN);
- }
- /**
- * Template function the check a condition for different types of users: root
- * graphics, system, and non-supported user. Root, graphics, and system should
- * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
- */
- template <typename T>
- void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
- // Check with root.
- seteuid(AID_ROOT);
- ASSERT_EQ(privilegedValue, condition());
- // Check as a Graphics user.
- setGraphicsUID();
- ASSERT_EQ(privilegedValue, condition());
- // Check as a system user.
- setSystemUID();
- ASSERT_EQ(privilegedValue, condition());
- // Check as a non-supported user.
- setBinUID();
- ASSERT_EQ(unprivilegedValue, condition());
- }
- };
- TEST_F(CredentialsTest, ClientInitTest) {
- // Root can init can init the client.
- ASSERT_NO_FATAL_FAILURE(initClient());
- // Graphics can init the client.
- setGraphicsUID();
- ASSERT_NO_FATAL_FAILURE(initClient());
- // System can init the client.
- setSystemUID();
- ASSERT_NO_FATAL_FAILURE(initClient());
- // Anyone else can init the client.
- setBinUID();
- mComposerClient = new SurfaceComposerClient;
- ASSERT_NO_FATAL_FAILURE(initClient());
- }
- TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
- std::function<bool()> condition = [] {
- return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
- };
- // Anyone can access display information.
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
- }
- TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
- // The following methods are tested with a UID that is not root, graphics,
- // or system, to show that anyone can access them.
- setBinUID();
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- ASSERT_TRUE(display != nullptr);
- DisplayInfo info;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
- Vector<DisplayInfo> configs;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
- ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
- SurfaceComposerClient::getActiveColorMode(display));
- }
- TEST_F(CredentialsTest, GetDisplayColorModesTest) {
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- std::function<status_t()> condition = [=]() {
- Vector<ui::ColorMode> outColorModes;
- return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
- }
- TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- std::function<status_t()> condition = [=]() {
- ui::DisplayPrimaries primaries;
- return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
- }
- TEST_F(CredentialsTest, SetActiveConfigTest) {
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- std::function<status_t()> condition = [=]() {
- return SurfaceComposerClient::setActiveConfig(display, 0);
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
- }
- TEST_F(CredentialsTest, SetActiveColorModeTest) {
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- std::function<status_t()> condition = [=]() {
- return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
- }
- TEST_F(CredentialsTest, CreateDisplayTest) {
- std::function<bool()> condition = [=]() {
- sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
- return testDisplay.get() != nullptr;
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
- condition = [=]() {
- sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
- return testDisplay.get() != nullptr;
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
- }
- TEST_F(CredentialsTest, DISABLED_DestroyDisplayTest) {
- setupVirtualDisplay();
- DisplayInfo info;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
- SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
- // This test currently fails. TODO(b/112002626): Find a way to properly create
- // a display in the test environment, so that destroy display can remove it.
- ASSERT_EQ(NAME_NOT_FOUND, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
- }
- TEST_F(CredentialsTest, CaptureTest) {
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- std::function<status_t()> condition = [=]() {
- sp<GraphicBuffer> outBuffer;
- return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB,
- ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/,
- 0 /*reqHeight*/, false, ROTATION, &outBuffer);
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
- }
- TEST_F(CredentialsTest, CaptureLayersTest) {
- setupBackgroundSurface();
- sp<GraphicBuffer> outBuffer;
- std::function<status_t()> condition = [=]() {
- sp<GraphicBuffer> outBuffer;
- return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(),
- ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
- Rect(), FRAME_SCALE, &outBuffer);
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
- }
- /**
- * The following tests are for methods accessible directly through SurfaceFlinger.
- */
- /**
- * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
- * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
- * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
- * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
- * the consumer of a buffer queue is SurfaceFlinger.
- */
- TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
- setupBackgroundSurface();
- sp<IGraphicBufferProducer> producer =
- mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
- // Anyone should be able to check if the consumer of the buffer queue is SF.
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
- }
- TEST_F(CredentialsTest, GetLayerDebugInfo) {
- setupBackgroundSurface();
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- // Historically, only root and shell can access the getLayerDebugInfo which
- // is called when we call dumpsys. I don't see a reason why we should change this.
- std::vector<LayerDebugInfo> outLayers;
- // Check with root.
- seteuid(AID_ROOT);
- ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
- // Check as a shell.
- seteuid(AID_SHELL);
- ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
- // Check as anyone else.
- seteuid(AID_ROOT);
- seteuid(AID_BIN);
- ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
- }
- TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- ASSERT_FALSE(display == nullptr);
- bool result = false;
- status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
- ASSERT_EQ(NO_ERROR, error);
- bool hasWideColorMode = false;
- Vector<ColorMode> colorModes;
- SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
- for (ColorMode colorMode : colorModes) {
- switch (colorMode) {
- case ColorMode::DISPLAY_P3:
- case ColorMode::ADOBE_RGB:
- case ColorMode::DCI_P3:
- hasWideColorMode = true;
- break;
- default:
- break;
- }
- }
- ASSERT_EQ(hasWideColorMode, result);
- }
- TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- ASSERT_FALSE(display == nullptr);
- std::function<status_t()> condition = [=]() {
- bool result = false;
- return SurfaceComposerClient::isWideColorDisplay(display, &result);
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
- }
- TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- ASSERT_FALSE(display == nullptr);
- ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display);
- ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
- }
- } // namespace android
|