Loading cmds/sfdo/sfdo.cpp +69 −14 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ #include <inttypes.h> #include <stdint.h> #include <any> #include <unordered_map> #include <map> #include <cutils/properties.h> #include <sys/resource.h> Loading @@ -29,18 +29,28 @@ using namespace android; std::unordered_map<std::string, std::any> g_functions; std::map<std::string, std::any> g_functions; const std::unordered_map<std::string, std::string> g_function_details = { {"DebugFlash", "[optional(delay)] Perform a debug flash."}, {"FrameRateIndicator", "[hide | show] displays the framerate in the top left corner."}, enum class ParseToggleResult { kError, kFalse, kTrue, }; const std::map<std::string, std::string> g_function_details = { {"debugFlash", "[optional(delay)] Perform a debug flash."}, {"frameRateIndicator", "[hide | show] displays the framerate in the top left corner."}, {"scheduleComposite", "Force composite ahead of next VSYNC."}, {"scheduleCommit", "Force commit ahead of next VSYNC."}, {"scheduleComposite", "PENDING - if you have a good understanding let me know!"}, {"forceClientComposition", "[enabled | disabled] When enabled, it disables " "Hardware Overlays, and routes all window composition to the GPU. This can " "help check if there is a bug in HW Composer."}, }; static void ShowUsage() { std::cout << "usage: sfdo [help, FrameRateIndicator show, DebugFlash enabled, ...]\n\n"; std::cout << "usage: sfdo [help, frameRateIndicator show, debugFlash enabled, ...]\n\n"; for (const auto& sf : g_functions) { const std::string fn = sf.first; std::string fdetails = "TODO"; Loading @@ -50,7 +60,26 @@ static void ShowUsage() { } } int FrameRateIndicator([[maybe_unused]] int argc, [[maybe_unused]] char** argv) { // Returns 1 for positive keywords and 0 for negative keywords. // If the string does not match any it will return -1. ParseToggleResult parseToggle(const char* str) { const std::unordered_set<std::string> positive{"1", "true", "y", "yes", "on", "enabled", "show"}; const std::unordered_set<std::string> negative{"0", "false", "n", "no", "off", "disabled", "hide"}; const std::string word(str); if (positive.count(word)) { return ParseToggleResult::kTrue; } if (negative.count(word)) { return ParseToggleResult::kFalse; } return ParseToggleResult::kError; } int frameRateIndicator(int argc, char** argv) { bool hide = false, show = false; if (argc == 3) { show = strcmp(argv[2], "show") == 0; Loading @@ -60,13 +89,13 @@ int FrameRateIndicator([[maybe_unused]] int argc, [[maybe_unused]] char** argv) if (show || hide) { ComposerServiceAIDL::getComposerService()->enableRefreshRateOverlay(show); } else { std::cerr << "Incorrect usage of FrameRateIndicator. Missing [hide | show].\n"; std::cerr << "Incorrect usage of frameRateIndicator. Missing [hide | show].\n"; return -1; } return 0; } int DebugFlash([[maybe_unused]] int argc, [[maybe_unused]] char** argv) { int debugFlash(int argc, char** argv) { int delay = 0; if (argc == 3) { delay = atoi(argv[2]) == 0; Loading @@ -86,14 +115,40 @@ int scheduleCommit([[maybe_unused]] int argc, [[maybe_unused]] char** argv) { return 0; } int forceClientComposition(int argc, char** argv) { bool enabled = true; // A valid command looks like this: // adb shell sfdo forceClientComposition enabled if (argc >= 3) { const ParseToggleResult toggle = parseToggle(argv[2]); if (toggle == ParseToggleResult::kError) { std::cerr << "Incorrect usage of forceClientComposition. " "Missing [enabled | disabled].\n"; return -1; } if (argc > 3) { std::cerr << "Too many arguments after [enabled | disabled]. " "Ignoring extra arguments.\n"; } enabled = (toggle == ParseToggleResult::kTrue); } else { std::cerr << "Incorrect usage of forceClientComposition. Missing [enabled | disabled].\n"; return -1; } ComposerServiceAIDL::getComposerService()->forceClientComposition(enabled); return 0; } int main(int argc, char** argv) { std::cout << "Execute SurfaceFlinger internal commands.\n"; std::cout << "sfdo requires to be run with root permissions..\n"; g_functions["FrameRateIndicator"] = FrameRateIndicator; g_functions["DebugFlash"] = DebugFlash; g_functions["frameRateIndicator"] = frameRateIndicator; g_functions["debugFlash"] = debugFlash; g_functions["scheduleComposite"] = scheduleComposite; g_functions["scheduleCommit"] = scheduleCommit; g_functions["forceClientComposition"] = forceClientComposition; if (argc > 1 && g_functions.find(argv[1]) != g_functions.end()) { std::cout << "Running: " << argv[1] << "\n"; Loading libs/gui/aidl/android/gui/ISurfaceComposer.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -513,6 +513,13 @@ interface ISurfaceComposer { */ void scheduleCommit(); /** * Force all window composition to the GPU (i.e. disable Hardware Overlays). * This can help check if there is a bug in HW Composer. * Requires root or android.permission.HARDWARE_TEST */ void forceClientComposition(boolean enabled); /** * Gets priority of the RenderEngine in SurfaceFlinger. */ Loading libs/gui/fuzzer/libgui_fuzzer_utils.h +1 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,7 @@ public: MOCK_METHOD(binder::Status, setDebugFlash, (int), (override)); MOCK_METHOD(binder::Status, scheduleComposite, (), (override)); MOCK_METHOD(binder::Status, scheduleCommit, (), (override)); MOCK_METHOD(binder::Status, forceClientComposition, (bool), (override)); MOCK_METHOD(binder::Status, updateSmallAreaDetection, (const std::vector<int32_t>&, const std::vector<float>&), (override)); MOCK_METHOD(binder::Status, setSmallAreaDetectionThreshold, (int32_t, float), (override)); Loading libs/gui/tests/Surface_test.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -934,6 +934,10 @@ public: binder::Status scheduleCommit() override { return binder::Status::ok(); } binder::Status forceClientComposition(bool /*enabled*/) override { return binder::Status::ok(); } binder::Status updateSmallAreaDetection(const std::vector<int32_t>& /*appIds*/, const std::vector<float>& /*thresholds*/) { return binder::Status::ok(); Loading services/surfaceflinger/SurfaceFlinger.cpp +11 −2 Original line number Diff line number Diff line Loading @@ -6769,8 +6769,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r case 1007: // Unused. return NAME_NOT_FOUND; case 1008: // Toggle forced GPU composition. mDebugDisableHWC = data.readInt32() != 0; scheduleRepaint(); sfdo_forceClientComposition(data.readInt32() != 0); return NO_ERROR; case 1009: // Toggle use of transform hint. mDebugDisableTransformHint = data.readInt32() != 0; Loading Loading @@ -9059,6 +9058,11 @@ void SurfaceFlinger::sfdo_scheduleCommit() { setTransactionFlags(eTransactionNeeded | eDisplayTransactionNeeded | eTraversalNeeded); } void SurfaceFlinger::sfdo_forceClientComposition(bool enabled) { mDebugDisableHWC = enabled; scheduleRepaint(); } // gui::ISurfaceComposer binder::Status SurfaceComposerAIDL::bootFinished() { Loading Loading @@ -9777,6 +9781,11 @@ binder::Status SurfaceComposerAIDL::scheduleCommit() { return binder::Status::ok(); } binder::Status SurfaceComposerAIDL::forceClientComposition(bool enabled) { mFlinger->sfdo_forceClientComposition(enabled); return binder::Status::ok(); } binder::Status SurfaceComposerAIDL::updateSmallAreaDetection(const std::vector<int32_t>& appIds, const std::vector<float>& thresholds) { status_t status; Loading Loading
cmds/sfdo/sfdo.cpp +69 −14 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ #include <inttypes.h> #include <stdint.h> #include <any> #include <unordered_map> #include <map> #include <cutils/properties.h> #include <sys/resource.h> Loading @@ -29,18 +29,28 @@ using namespace android; std::unordered_map<std::string, std::any> g_functions; std::map<std::string, std::any> g_functions; const std::unordered_map<std::string, std::string> g_function_details = { {"DebugFlash", "[optional(delay)] Perform a debug flash."}, {"FrameRateIndicator", "[hide | show] displays the framerate in the top left corner."}, enum class ParseToggleResult { kError, kFalse, kTrue, }; const std::map<std::string, std::string> g_function_details = { {"debugFlash", "[optional(delay)] Perform a debug flash."}, {"frameRateIndicator", "[hide | show] displays the framerate in the top left corner."}, {"scheduleComposite", "Force composite ahead of next VSYNC."}, {"scheduleCommit", "Force commit ahead of next VSYNC."}, {"scheduleComposite", "PENDING - if you have a good understanding let me know!"}, {"forceClientComposition", "[enabled | disabled] When enabled, it disables " "Hardware Overlays, and routes all window composition to the GPU. This can " "help check if there is a bug in HW Composer."}, }; static void ShowUsage() { std::cout << "usage: sfdo [help, FrameRateIndicator show, DebugFlash enabled, ...]\n\n"; std::cout << "usage: sfdo [help, frameRateIndicator show, debugFlash enabled, ...]\n\n"; for (const auto& sf : g_functions) { const std::string fn = sf.first; std::string fdetails = "TODO"; Loading @@ -50,7 +60,26 @@ static void ShowUsage() { } } int FrameRateIndicator([[maybe_unused]] int argc, [[maybe_unused]] char** argv) { // Returns 1 for positive keywords and 0 for negative keywords. // If the string does not match any it will return -1. ParseToggleResult parseToggle(const char* str) { const std::unordered_set<std::string> positive{"1", "true", "y", "yes", "on", "enabled", "show"}; const std::unordered_set<std::string> negative{"0", "false", "n", "no", "off", "disabled", "hide"}; const std::string word(str); if (positive.count(word)) { return ParseToggleResult::kTrue; } if (negative.count(word)) { return ParseToggleResult::kFalse; } return ParseToggleResult::kError; } int frameRateIndicator(int argc, char** argv) { bool hide = false, show = false; if (argc == 3) { show = strcmp(argv[2], "show") == 0; Loading @@ -60,13 +89,13 @@ int FrameRateIndicator([[maybe_unused]] int argc, [[maybe_unused]] char** argv) if (show || hide) { ComposerServiceAIDL::getComposerService()->enableRefreshRateOverlay(show); } else { std::cerr << "Incorrect usage of FrameRateIndicator. Missing [hide | show].\n"; std::cerr << "Incorrect usage of frameRateIndicator. Missing [hide | show].\n"; return -1; } return 0; } int DebugFlash([[maybe_unused]] int argc, [[maybe_unused]] char** argv) { int debugFlash(int argc, char** argv) { int delay = 0; if (argc == 3) { delay = atoi(argv[2]) == 0; Loading @@ -86,14 +115,40 @@ int scheduleCommit([[maybe_unused]] int argc, [[maybe_unused]] char** argv) { return 0; } int forceClientComposition(int argc, char** argv) { bool enabled = true; // A valid command looks like this: // adb shell sfdo forceClientComposition enabled if (argc >= 3) { const ParseToggleResult toggle = parseToggle(argv[2]); if (toggle == ParseToggleResult::kError) { std::cerr << "Incorrect usage of forceClientComposition. " "Missing [enabled | disabled].\n"; return -1; } if (argc > 3) { std::cerr << "Too many arguments after [enabled | disabled]. " "Ignoring extra arguments.\n"; } enabled = (toggle == ParseToggleResult::kTrue); } else { std::cerr << "Incorrect usage of forceClientComposition. Missing [enabled | disabled].\n"; return -1; } ComposerServiceAIDL::getComposerService()->forceClientComposition(enabled); return 0; } int main(int argc, char** argv) { std::cout << "Execute SurfaceFlinger internal commands.\n"; std::cout << "sfdo requires to be run with root permissions..\n"; g_functions["FrameRateIndicator"] = FrameRateIndicator; g_functions["DebugFlash"] = DebugFlash; g_functions["frameRateIndicator"] = frameRateIndicator; g_functions["debugFlash"] = debugFlash; g_functions["scheduleComposite"] = scheduleComposite; g_functions["scheduleCommit"] = scheduleCommit; g_functions["forceClientComposition"] = forceClientComposition; if (argc > 1 && g_functions.find(argv[1]) != g_functions.end()) { std::cout << "Running: " << argv[1] << "\n"; Loading
libs/gui/aidl/android/gui/ISurfaceComposer.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -513,6 +513,13 @@ interface ISurfaceComposer { */ void scheduleCommit(); /** * Force all window composition to the GPU (i.e. disable Hardware Overlays). * This can help check if there is a bug in HW Composer. * Requires root or android.permission.HARDWARE_TEST */ void forceClientComposition(boolean enabled); /** * Gets priority of the RenderEngine in SurfaceFlinger. */ Loading
libs/gui/fuzzer/libgui_fuzzer_utils.h +1 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,7 @@ public: MOCK_METHOD(binder::Status, setDebugFlash, (int), (override)); MOCK_METHOD(binder::Status, scheduleComposite, (), (override)); MOCK_METHOD(binder::Status, scheduleCommit, (), (override)); MOCK_METHOD(binder::Status, forceClientComposition, (bool), (override)); MOCK_METHOD(binder::Status, updateSmallAreaDetection, (const std::vector<int32_t>&, const std::vector<float>&), (override)); MOCK_METHOD(binder::Status, setSmallAreaDetectionThreshold, (int32_t, float), (override)); Loading
libs/gui/tests/Surface_test.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -934,6 +934,10 @@ public: binder::Status scheduleCommit() override { return binder::Status::ok(); } binder::Status forceClientComposition(bool /*enabled*/) override { return binder::Status::ok(); } binder::Status updateSmallAreaDetection(const std::vector<int32_t>& /*appIds*/, const std::vector<float>& /*thresholds*/) { return binder::Status::ok(); Loading
services/surfaceflinger/SurfaceFlinger.cpp +11 −2 Original line number Diff line number Diff line Loading @@ -6769,8 +6769,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r case 1007: // Unused. return NAME_NOT_FOUND; case 1008: // Toggle forced GPU composition. mDebugDisableHWC = data.readInt32() != 0; scheduleRepaint(); sfdo_forceClientComposition(data.readInt32() != 0); return NO_ERROR; case 1009: // Toggle use of transform hint. mDebugDisableTransformHint = data.readInt32() != 0; Loading Loading @@ -9059,6 +9058,11 @@ void SurfaceFlinger::sfdo_scheduleCommit() { setTransactionFlags(eTransactionNeeded | eDisplayTransactionNeeded | eTraversalNeeded); } void SurfaceFlinger::sfdo_forceClientComposition(bool enabled) { mDebugDisableHWC = enabled; scheduleRepaint(); } // gui::ISurfaceComposer binder::Status SurfaceComposerAIDL::bootFinished() { Loading Loading @@ -9777,6 +9781,11 @@ binder::Status SurfaceComposerAIDL::scheduleCommit() { return binder::Status::ok(); } binder::Status SurfaceComposerAIDL::forceClientComposition(bool enabled) { mFlinger->sfdo_forceClientComposition(enabled); return binder::Status::ok(); } binder::Status SurfaceComposerAIDL::updateSmallAreaDetection(const std::vector<int32_t>& appIds, const std::vector<float>& thresholds) { status_t status; Loading