Merge "Add a flag for refresh rate switching"
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
new file mode 100644
index 0000000..40b8dc7
--- /dev/null
+++ b/cmds/idlcli/Android.bp
@@ -0,0 +1,53 @@
+// Copyright (C) 2019 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.
+
+cc_defaults {
+ name: "idlcli-defaults",
+ shared_libs: [
+ "android.hardware.vibrator@1.0",
+ "android.hardware.vibrator@1.1",
+ "android.hardware.vibrator@1.2",
+ "android.hardware.vibrator@1.3",
+ "libbase",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"idlcli\"",
+ ],
+}
+
+cc_library {
+ name: "libidlcli",
+ defaults: ["idlcli-defaults"],
+ srcs: [
+ "CommandVibrator.cpp",
+ "vibrator/CommandOff.cpp",
+ "vibrator/CommandOn.cpp",
+ "vibrator/CommandPerform.cpp",
+ "vibrator/CommandSetAmplitude.cpp",
+ "vibrator/CommandSetExternalControl.cpp",
+ "vibrator/CommandSupportsAmplitudeControl.cpp",
+ "vibrator/CommandSupportsExternalControl.cpp",
+ ],
+ visibility: [":__subpackages__"],
+}
+
+cc_binary {
+ name: "idlcli",
+ defaults: ["idlcli-defaults"],
+ srcs: ["main.cpp"],
+ whole_static_libs: ["libidlcli"],
+}
diff --git a/cmds/idlcli/CommandVibrator.cpp b/cmds/idlcli/CommandVibrator.cpp
new file mode 100644
index 0000000..a7a70c3
--- /dev/null
+++ b/cmds/idlcli/CommandVibrator.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "utils.h"
+
+namespace android {
+namespace idlcli {
+
+class IdlCli;
+
+class CommandVibrator : public CommandWithSubcommands<CommandVibrator> {
+ std::string getDescription() const override { return "Invoke Vibrator HIDL APIs."; }
+
+ std::string getUsageSummary() const override { return "<api> [arguments]"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<api>", CommandRegistry<CommandVibrator>::List()},
+ };
+ return details;
+ }
+};
+
+static const auto Command = CommandRegistry<IdlCli>::Register<CommandVibrator>("vibrator");
+
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/IdlCli.h b/cmds/idlcli/IdlCli.h
new file mode 100644
index 0000000..dd84304
--- /dev/null
+++ b/cmds/idlcli/IdlCli.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 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 FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
+#define FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
+
+#include "utils.h"
+
+namespace android {
+namespace idlcli {
+
+class IdlCli : public CommandWithSubcommands<IdlCli> {
+ std::string getDescription() const override { return "Invoke IDL APIs."; }
+
+ std::string getUsageSummary() const override { return "<idl> [arguments]"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<idl>", CommandRegistry<IdlCli>::List()},
+ };
+ return details;
+ }
+};
+
+} // namespace idlcli
+} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
diff --git a/cmds/idlcli/main.cpp b/cmds/idlcli/main.cpp
new file mode 100644
index 0000000..9ed9d82
--- /dev/null
+++ b/cmds/idlcli/main.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "IdlCli.h"
+#include "utils.h"
+
+int main(const int argc, const char* const argv[]) {
+ using namespace ::android::idlcli;
+ return IdlCli{}.main(Args{argc, argv});
+}
diff --git a/cmds/idlcli/utils.h b/cmds/idlcli/utils.h
new file mode 100644
index 0000000..a8e5954
--- /dev/null
+++ b/cmds/idlcli/utils.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2019 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 FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
+#define FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
+
+#include <hidl/HidlSupport.h>
+
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace idlcli {
+
+namespace overrides {
+
+namespace details {
+
+template <typename T>
+inline std::istream &operator>>(std::istream &stream, T &out) {
+ auto pos = stream.tellg();
+ auto tmp = +out;
+ auto min = +std::numeric_limits<T>::min();
+ auto max = +std::numeric_limits<T>::max();
+ stream >> tmp;
+ if (!stream) {
+ return stream;
+ }
+ if (tmp < min || tmp > max) {
+ stream.seekg(pos);
+ stream.setstate(std::ios_base::failbit);
+ return stream;
+ }
+ out = tmp;
+ return stream;
+}
+
+} // namespace details
+
+// override for default behavior of treating as a character
+inline std::istream &operator>>(std::istream &stream, int8_t &out) {
+ return details::operator>>(stream, out);
+}
+
+// override for default behavior of treating as a character
+inline std::istream &operator>>(std::istream &stream, uint8_t &out) {
+ return details::operator>>(stream, out);
+}
+
+} // namespace overrides
+
+template <typename T, typename R = hardware::hidl_enum_range<T>>
+inline std::istream &operator>>(std::istream &stream, T &out) {
+ using overrides::operator>>;
+ auto validRange = R();
+ auto pos = stream.tellg();
+ std::underlying_type_t<T> in;
+ T tmp;
+ stream >> in;
+ if (!stream) {
+ return stream;
+ }
+ tmp = static_cast<T>(in);
+ if (tmp < *validRange.begin() || tmp > *std::prev(validRange.end())) {
+ stream.seekg(pos);
+ stream.setstate(std::ios_base::failbit);
+ return stream;
+ }
+ out = tmp;
+ return stream;
+}
+
+enum Status : unsigned int {
+ OK,
+ USAGE,
+ UNAVAILABLE,
+ ERROR,
+};
+
+class Args {
+public:
+ Args(const int argc, const char *const argv[]) {
+ for (int argi = 0; argi < argc; argi++) {
+ mArgs.emplace_back(std::string_view(argv[argi]));
+ }
+ }
+
+ template <typename T = std::string>
+ std::optional<T> get() {
+ return get<T>(false);
+ }
+
+ template <typename T = std::string>
+ std::optional<T> pop() {
+ return get<T>(true);
+ }
+
+ bool empty() { return mArgs.empty(); }
+
+private:
+ template <typename T>
+ std::optional<T> get(bool erase) {
+ using idlcli::operator>>;
+ using overrides::operator>>;
+ T retValue;
+
+ if (mArgs.empty()) {
+ return {};
+ }
+
+ std::stringstream stream{std::string{mArgs.front()}};
+ stream >> std::setbase(0) >> retValue;
+ if (!stream || !stream.eof()) {
+ return {};
+ }
+
+ if (erase) {
+ mArgs.erase(mArgs.begin());
+ }
+
+ return retValue;
+ }
+
+ std::vector<std::string_view> mArgs;
+};
+
+class Command {
+protected:
+ struct Usage {
+ std::string name;
+ std::vector<std::string> details;
+ };
+ using UsageDetails = std::vector<Usage>;
+
+public:
+ virtual ~Command() = default;
+
+ Status main(Args &&args) {
+ Status status = doArgsAndMain(std::move(args));
+ if (status == USAGE) {
+ printUsage();
+ return ERROR;
+ }
+ if (status == UNAVAILABLE) {
+ std::cerr << "The requested operation is unavailable." << std::endl;
+ return ERROR;
+ }
+ return status;
+ }
+
+private:
+ virtual std::string getDescription() const = 0;
+ virtual std::string getUsageSummary() const = 0;
+ virtual UsageDetails getUsageDetails() const = 0;
+ virtual Status doArgs(Args &args) = 0;
+ virtual Status doMain(Args &&args) = 0;
+
+ void printUsage() const {
+ std::cerr << "Description:\n " << getDescription() << std::endl;
+ std::cerr << "Usage:\n " << mName << " " << getUsageSummary() << std::endl;
+
+ std::cerr << "Details:" << std::endl;
+ size_t entryNameWidth = 0;
+ for (auto &entry : getUsageDetails()) {
+ entryNameWidth = std::max(entryNameWidth, entry.name.length());
+ }
+ for (auto &entry : getUsageDetails()) {
+ auto prefix = entry.name;
+ for (auto &line : entry.details) {
+ std::cerr << " " << std::left << std::setw(entryNameWidth + 8) << prefix << line
+ << std::endl;
+ prefix = "";
+ }
+ }
+ }
+
+ Status doArgsAndMain(Args &&args) {
+ Status status;
+ mName = *args.pop();
+ if ((status = doArgs(args)) != OK) {
+ return status;
+ }
+ if ((status = doMain(std::move(args))) != OK) {
+ return status;
+ }
+ return OK;
+ }
+
+protected:
+ std::string mName;
+};
+
+template <typename T>
+class CommandRegistry {
+private:
+ using CommandCreator = std::function<std::unique_ptr<Command>()>;
+
+public:
+ template <typename U>
+ static CommandCreator Register(const std::string name) {
+ Instance()->mCommands[name] = [] { return std::make_unique<U>(); };
+ return Instance()->mCommands[name];
+ }
+
+ static std::unique_ptr<Command> Create(const std::string name) {
+ auto it = Instance()->mCommands.find(name);
+ if (it == Instance()->mCommands.end()) {
+ return nullptr;
+ }
+ return it->second();
+ }
+
+ static auto List() {
+ std::vector<std::string> list;
+ for (auto &it : Instance()->mCommands) {
+ list.push_back(it.first);
+ }
+ std::sort(list.begin(), list.end());
+ return list;
+ }
+
+private:
+ static CommandRegistry *Instance() {
+ static CommandRegistry sRegistry;
+ return &sRegistry;
+ }
+
+private:
+ std::map<const std::string, CommandCreator> mCommands;
+};
+
+template <typename T>
+class CommandWithSubcommands : public Command {
+private:
+ Status doArgs(Args &args) override {
+ mCommand = CommandRegistry<T>::Create(*args.get());
+ if (!mCommand) {
+ std::cerr << "Invalid Command!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args &&args) override { return mCommand->main(std::move(args)); }
+
+protected:
+ std::unique_ptr<Command> mCommand;
+};
+
+} // namespace idlcli
+} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h
new file mode 100644
index 0000000..bcb207b
--- /dev/null
+++ b/cmds/idlcli/vibrator.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 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 FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
+#define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
+
+#include <android/hardware/vibrator/1.3/IVibrator.h>
+
+#include "utils.h"
+
+#include "log/log.h"
+
+namespace android {
+
+using hardware::Return;
+
+static constexpr int NUM_TRIES = 2;
+
+// Creates a Return<R> with STATUS::EX_NULL_POINTER.
+template <class R>
+inline Return<R> NullptrStatus() {
+ using ::android::hardware::Status;
+ return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
+}
+
+template <typename I>
+class HalWrapper {
+public:
+ static std::unique_ptr<HalWrapper> Create() {
+ // Assume that if getService returns a nullptr, HAL is not available on the
+ // device.
+ auto hal = I::getService();
+ return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
+ }
+
+ template <class R, class... Args0, class... Args1>
+ Return<R> call(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
+ return (*mHal.*fn)(std::forward<Args1>(args1)...);
+ }
+
+private:
+ HalWrapper(sp<I>&& hal) : mHal(std::move(hal)) {}
+
+private:
+ sp<I> mHal;
+};
+
+template <typename I>
+static auto getHal() {
+ static auto sHalWrapper = HalWrapper<I>::Create();
+ return sHalWrapper.get();
+}
+
+template <class R, class I, class... Args0, class... Args1>
+Return<R> halCall(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
+ auto hal = getHal<I>();
+ return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
+}
+
+namespace idlcli {
+namespace vibrator {
+
+namespace V1_0 = ::android::hardware::vibrator::V1_0;
+namespace V1_1 = ::android::hardware::vibrator::V1_1;
+namespace V1_2 = ::android::hardware::vibrator::V1_2;
+namespace V1_3 = ::android::hardware::vibrator::V1_3;
+
+} // namespace vibrator
+} // namespace idlcli
+
+} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
diff --git a/cmds/idlcli/vibrator/CommandOff.cpp b/cmds/idlcli/vibrator/CommandOff.cpp
new file mode 100644
index 0000000..a674f01
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandOff.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandOff : public Command {
+ std::string getDescription() const override { return "Turn off vibrator."; }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_0::IVibrator::off);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(ret) << std::endl;
+
+ return ret == V1_0::Status::OK ? OK : ERROR;
+ }
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOff>("off");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandOn.cpp b/cmds/idlcli/vibrator/CommandOn.cpp
new file mode 100644
index 0000000..2164b7d
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandOn.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandOn : public Command {
+ std::string getDescription() const override { return "Turn on vibrator."; }
+
+ std::string getUsageSummary() const override { return "<duration>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<duration>", {"In milliseconds."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (auto duration = args.pop<decltype(mDuration)>()) {
+ mDuration = *duration;
+ } else {
+ std::cerr << "Missing or Invalid Duration!" << std::endl;
+ return USAGE;
+ }
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_0::IVibrator::on, mDuration);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(ret) << std::endl;
+
+ return ret == V1_0::Status::OK ? OK : ERROR;
+ }
+
+ uint32_t mDuration;
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOn>("on");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandPerform.cpp b/cmds/idlcli/vibrator/CommandPerform.cpp
new file mode 100644
index 0000000..688cbd8
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandPerform.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using V1_0::EffectStrength;
+using V1_3::Effect;
+
+class CommandPerform : public Command {
+ std::string getDescription() const override { return "Perform vibration effect."; }
+
+ std::string getUsageSummary() const override { return "<effect> <strength>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<effect>", {"Effect ID."}},
+ {"<strength>", {"0-2."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (auto effect = args.pop<decltype(mEffect)>()) {
+ mEffect = *effect;
+ std::cout << "Effect: " << toString(mEffect) << std::endl;
+ } else {
+ std::cerr << "Missing or Invalid Effect!" << std::endl;
+ return USAGE;
+ }
+ if (auto strength = args.pop<decltype(mStrength)>()) {
+ mStrength = *strength;
+ std::cout << "Strength: " << toString(mStrength) << std::endl;
+ } else {
+ std::cerr << "Missing or Invalid Strength!" << std::endl;
+ return USAGE;
+ }
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ Return<void> ret;
+ V1_0::Status status;
+ uint32_t lengthMs;
+ auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
+ status = retStatus;
+ lengthMs = retLengthMs;
+ };
+
+ if (auto hal = getHal<V1_3::IVibrator>()) {
+ ret = hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect),
+ mStrength, callback);
+ } else if (auto hal = getHal<V1_2::IVibrator>()) {
+ ret = hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect),
+ mStrength, callback);
+ } else if (auto hal = getHal<V1_1::IVibrator>()) {
+ ret = hal->call(&V1_1::IVibrator::perform_1_1, static_cast<V1_1::Effect_1_1>(mEffect),
+ mStrength, callback);
+ } else if (auto hal = getHal<V1_0::IVibrator>()) {
+ ret = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
+ mStrength, callback);
+ } else {
+ ret = NullptrStatus<void>();
+ }
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(status) << std::endl;
+ std::cout << "Length: " << lengthMs << std::endl;
+
+ return status == V1_0::Status::OK ? OK : ERROR;
+ }
+
+ Effect mEffect;
+ EffectStrength mStrength;
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandPerform>("perform");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
new file mode 100644
index 0000000..38a1dc2
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandSetAmplitude : public Command {
+ std::string getDescription() const override { return "Set vibration amplitude."; }
+
+ std::string getUsageSummary() const override { return "<amplitude>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<amplitude>", {"1-255."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (auto amplitude = args.pop<decltype(mAmplitude)>()) {
+ mAmplitude = *amplitude;
+ } else {
+ std::cerr << "Missing or Invalid Amplitude!" << std::endl;
+ return USAGE;
+ }
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_0::IVibrator::setAmplitude, mAmplitude);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(ret) << std::endl;
+
+ return ret == V1_0::Status::OK ? OK : ERROR;
+ }
+
+ uint8_t mAmplitude;
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandSetAmplitude>("setAmplitude");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
new file mode 100644
index 0000000..5fb1fac
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandSetExternalControl : public Command {
+ std::string getDescription() const override {
+ return "Enable/disable vibration external control.";
+ }
+
+ std::string getUsageSummary() const override { return "<enable>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<enable>", {"0/1."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (auto enable = args.pop<decltype(mEnable)>()) {
+ mEnable = *enable;
+ } else {
+ std::cerr << "Missing Enable!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_3::IVibrator::setExternalControl, mEnable);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(ret) << std::endl;
+
+ return ret == V1_0::Status::OK ? OK : ERROR;
+ }
+
+ bool mEnable;
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandSetExternalControl>("setExternalControl");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
new file mode 100644
index 0000000..cdc529a
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandSupportsAmplitudeControl : public Command {
+ std::string getDescription() const override { return "Check support for amplitude control."; }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_0::IVibrator::supportsAmplitudeControl);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Result: " << std::boolalpha << ret << std::endl;
+
+ return OK;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandSupportsAmplitudeControl>(
+ "supportsAmplitudeControl");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
new file mode 100644
index 0000000..ed15d76
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandSupportsExternalControl : public Command {
+ std::string getDescription() const override { return "Check support for external control."; }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_3::IVibrator::supportsExternalControl);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Result: " << std::boolalpha << ret << std::endl;
+
+ return OK;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandSupportsExternalControl>(
+ "supportsExternalControl");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 7e356e4..aad1849 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1081,6 +1081,9 @@
case NATIVE_WINDOW_SET_AUTO_PREROTATION:
res = dispatchSetAutoPrerotation(args);
break;
+ case NATIVE_WINDOW_GET_LAST_DEQUEUE_START:
+ res = dispatchGetLastDequeueStartTime(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -1286,6 +1289,12 @@
return setAutoPrerotation(autoPrerotation);
}
+int Surface::dispatchGetLastDequeueStartTime(va_list args) {
+ int64_t* lastDequeueStartTime = va_arg(args, int64_t*);
+ *lastDequeueStartTime = mLastDequeueStartTime;
+ return NO_ERROR;
+}
+
bool Surface::transformToDisplayInverse() {
return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
@@ -1950,11 +1959,6 @@
return mGraphicBufferProducer->getConsumerUsage(outUsage);
}
-nsecs_t Surface::getLastDequeueStartTime() const {
- Mutex::Autolock lock(mMutex);
- return mLastDequeueStartTime;
-}
-
status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out) {
if (out == nullptr) {
ALOGE("%s: out must not be null!", __FUNCTION__);
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 28f5a26..5bcfcda 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -179,9 +179,6 @@
status_t getUniqueId(uint64_t* outId) const;
status_t getConsumerUsage(uint64_t* outUsage) const;
- // Returns the CLOCK_MONOTONIC start time of the last dequeueBuffer call
- nsecs_t getLastDequeueStartTime() const;
-
protected:
virtual ~Surface();
@@ -247,6 +244,7 @@
int dispatchGetHdrSupport(va_list args);
int dispatchGetConsumerUsage64(va_list args);
int dispatchSetAutoPrerotation(va_list args);
+ int dispatchGetLastDequeueStartTime(va_list args);
bool transformToDisplayInverse();
protected:
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 5a121d7..0b61d92 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -617,7 +617,7 @@
anw->dequeueBuffer(anw.get(), &buffer, &fenceFd);
nsecs_t after = systemTime(CLOCK_MONOTONIC);
- nsecs_t lastDequeueTime = mSurface->getLastDequeueStartTime();
+ nsecs_t lastDequeueTime = ANativeWindow_getLastDequeueStartTime(anw.get());
ASSERT_LE(before, lastDequeueTime);
ASSERT_GE(after, lastDequeueTime);
}
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 4c59e6c..3b195f7 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -274,3 +274,13 @@
int ANativeWindow_getLastDequeueDuration(ANativeWindow* window) {
return query(window, NATIVE_WINDOW_LAST_DEQUEUE_DURATION);
}
+
+int ANativeWindow_getLastQueueDuration(ANativeWindow* window) {
+ return query(window, NATIVE_WINDOW_LAST_QUEUE_DURATION);
+}
+
+int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window) {
+ int64_t time;
+ int success = window->perform(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_START, &time);
+ return success < 0 ? success : time;
+}
diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h
index 0260cbc..3ddd549 100644
--- a/libs/nativewindow/include/apex/window.h
+++ b/libs/nativewindow/include/apex/window.h
@@ -31,4 +31,21 @@
*/
int ANativeWindow_getLastDequeueDuration(ANativeWindow* window);
+/**
+ * Retrieves how long it took for the last time a buffer was queued.
+ *
+ * \return a negative value on error, otherwise returns the duration in
+ * microseconds
+ */
+int ANativeWindow_getLastQueueDuration(ANativeWindow* window);
+
+/**
+ * Retrieves the system time in nanoseconds when the last time a buffer
+ * was dequeued.
+ *
+ * \return a negative value on error, otherwise returns the duration in
+ * nanoseconds.
+ */
+int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window);
+
__END_DECLS
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 78354bb..b7ae28a 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -93,7 +93,6 @@
*/
NATIVE_WINDOW_CONCRETE_TYPE = 5,
-
/*
* Default width and height of ANativeWindow buffers, these are the
* dimensions of the window buffers irrespective of the
@@ -240,6 +239,7 @@
NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33,
NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA = 34,
NATIVE_WINDOW_SET_AUTO_PREROTATION = 35,
+ NATIVE_WINDOW_GET_LAST_DEQUEUE_START = 36, /* private */
// clang-format on
};
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index 7fe4df0..33c6400 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -23,6 +23,8 @@
ANativeWindow_getFormat;
ANativeWindow_getHeight;
ANativeWindow_getLastDequeueDuration; # apex # introduced=30
+ ANativeWindow_getLastDequeueStartTime; # apex # introduced=30
+ ANativeWindow_getLastQueueDuration; # apex # introduced=30
ANativeWindow_getWidth;
ANativeWindow_lock;
ANativeWindow_query; # vndk
diff --git a/libs/nativewindow/tests/ANativeWindowTest.cpp b/libs/nativewindow/tests/ANativeWindowTest.cpp
index 5247e04..947217d 100644
--- a/libs/nativewindow/tests/ANativeWindowTest.cpp
+++ b/libs/nativewindow/tests/ANativeWindowTest.cpp
@@ -36,6 +36,12 @@
// Exposes the internal last dequeue duration that's stored on the Surface.
nsecs_t getLastDequeueDuration() const { return mLastDequeueDuration; }
+
+ // Exposes the internal last queue duration that's stored on the Surface.
+ nsecs_t getLastQueueDuration() const { return mLastQueueDuration; }
+
+ // Exposes the internal last dequeue start time that's stored on the Surface.
+ nsecs_t getLastDequeueStartTime() const { return mLastDequeueStartTime; }
};
class ANativeWindowTest : public ::testing::Test {
@@ -82,3 +88,53 @@
EXPECT_GT(result, 0);
EXPECT_EQ(result, mWindow->getLastDequeueDuration() / 1000);
}
+
+TEST_F(ANativeWindowTest, getLastQueueDuration_noDequeue_returnsZero) {
+ int result = ANativeWindow_getLastQueueDuration(mWindow.get());
+ EXPECT_EQ(0, result);
+ EXPECT_EQ(0, mWindow->getLastQueueDuration());
+}
+
+TEST_F(ANativeWindowTest, getLastQueueDuration_noQueue_returnsZero) {
+ ANativeWindowBuffer* buffer;
+ int fd;
+ int result = ANativeWindow_dequeueBuffer(mWindow.get(), &buffer, &fd);
+ close(fd);
+ EXPECT_EQ(0, result);
+
+ result = ANativeWindow_getLastQueueDuration(mWindow.get());
+ EXPECT_EQ(result, 0);
+ EXPECT_EQ(result, mWindow->getLastQueueDuration());
+}
+
+TEST_F(ANativeWindowTest, getLastQueueDuration_withQueue_returnsTime) {
+ ANativeWindowBuffer* buffer;
+ int fd;
+ int result = ANativeWindow_dequeueBuffer(mWindow.get(), &buffer, &fd);
+ close(fd);
+ EXPECT_EQ(0, result);
+
+ result = ANativeWindow_queueBuffer(mWindow.get(), buffer, 0);
+
+ result = ANativeWindow_getLastQueueDuration(mWindow.get());
+ EXPECT_GT(result, 0);
+ EXPECT_EQ(result, mWindow->getLastQueueDuration() / 1000);
+}
+
+TEST_F(ANativeWindowTest, getLastDequeueStartTime_noDequeue_returnsZero) {
+ int64_t result = ANativeWindow_getLastDequeueStartTime(mWindow.get());
+ EXPECT_EQ(0, result);
+ EXPECT_EQ(0, mWindow->getLastQueueDuration());
+}
+
+TEST_F(ANativeWindowTest, getLastDequeueStartTime_withDequeue_returnsTime) {
+ ANativeWindowBuffer* buffer;
+ int fd;
+ int dequeueResult = ANativeWindow_dequeueBuffer(mWindow.get(), &buffer, &fd);
+ close(fd);
+ EXPECT_EQ(0, dequeueResult);
+
+ int64_t result = ANativeWindow_getLastDequeueStartTime(mWindow.get());
+ EXPECT_GT(result, 0);
+ EXPECT_EQ(result, mWindow->getLastDequeueStartTime());
+}
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 1cbf78e..d59f274 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -1141,13 +1141,24 @@
}
}
- setEnabled(enabled, when);
+ if (changes) {
+ // For first-time configuration, only allow device to be disabled after mappers have
+ // finished configuring. This is because we need to read some of the properties from
+ // the device's open fd.
+ setEnabled(enabled, when);
+ }
}
for (InputMapper* mapper : mMappers) {
mapper->configure(when, config, changes);
mSources |= mapper->getSources();
}
+
+ // If a device is just plugged but it might be disabled, we need to update some info like
+ // axis range of touch from each InputMapper first, then disable it.
+ if (!changes) {
+ setEnabled(config->disabledDevices.find(mId) == config->disabledDevices.end(), when);
+ }
}
}
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 348a12b..09df2a7 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -527,7 +527,7 @@
virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
RawAbsoluteAxisInfo* outAxisInfo) const {
Device* device = getDevice(deviceId);
- if (device) {
+ if (device && device->enabled) {
ssize_t index = device->absoluteAxes.indexOfKey(axis);
if (index >= 0) {
*outAxisInfo = device->absoluteAxes.valueAt(index);
@@ -6554,4 +6554,35 @@
ASSERT_EQ(frames, motionArgs.videoFrames);
}
+/**
+ * If we had defined port associations, but the viewport is not ready, the touch device would be
+ * expected to be disabled, and it should be enabled after the viewport has found.
+ */
+TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+ constexpr uint8_t hdmi2 = 1;
+ const std::string secondaryUniqueId = "uniqueId2";
+ constexpr ViewportType type = ViewportType::VIEWPORT_EXTERNAL;
+
+ mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
+
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareAxes(POSITION);
+ addMapperAndConfigure(mapper);
+
+ ASSERT_EQ(mDevice->isEnabled(), false);
+
+ // Add display on hdmi2, the device should be enabled and can receive touch event.
+ prepareSecondaryDisplay(type, hdmi2);
+ ASSERT_EQ(mDevice->isEnabled(), true);
+
+ // Send a touch event.
+ processPosition(mapper, 100, 100);
+ processSync(mapper);
+
+ NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
+}
+
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2899034..c01d3aa 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -340,11 +340,6 @@
mPropagateBackpressure = !atoi(value);
ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
- property_get("debug.sf.enable_gl_backpressure", value, "0");
- mPropagateBackpressureClientComposition = atoi(value);
- ALOGI_IF(mPropagateBackpressureClientComposition,
- "Enabling backpressure propagation for Client Composition");
-
property_get("debug.sf.enable_hwc_vds", value, "0");
mUseHwcVirtualDisplays = atoi(value);
ALOGI_IF(mUseHwcVirtualDisplays, "Enabling HWC virtual displays");
@@ -1652,9 +1647,9 @@
break;
}
- if (frameMissed && mPropagateBackpressure) {
- if ((hwcFrameMissed && !gpuFrameMissed) ||
- mPropagateBackpressureClientComposition) {
+ // For now, only propagate backpressure when missing a hwc frame.
+ if (hwcFrameMissed && !gpuFrameMissed) {
+ if (mPropagateBackpressure) {
signalLayerUpdate();
break;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d357c3d..aaa50f6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -983,7 +983,6 @@
volatile nsecs_t mDebugInTransaction = 0;
bool mForceFullDamage = false;
bool mPropagateBackpressure = true;
- bool mPropagateBackpressureClientComposition = false;
std::unique_ptr<SurfaceInterceptor> mInterceptor;
SurfaceTracing mTracing{*this};
bool mTracingEnabled = false;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index b01fa81..3df8360 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -34,6 +34,14 @@
namespace impl {
+TimeStats::TimeStats() {
+ // Temporarily enable TimeStats by default. Telemetry is disabled while
+ // we move onto statsd, so TimeStats is currently not exercised at all
+ // during testing.
+ // TODO: remove this.
+ enable();
+}
+
void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, std::string& result) {
ATRACE_CALL();
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 9ebc1ad..1313132 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -106,7 +106,7 @@
};
public:
- TimeStats() = default;
+ TimeStats();
void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
bool isEnabled() override;
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index ffacbfe..dee2cae 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -209,6 +209,10 @@
return distr(mRandomEngine);
}
+TEST_F(TimeStatsTest, enabledByDefault) {
+ ASSERT_TRUE(mTimeStats->isEnabled());
+}
+
TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
ASSERT_TRUE(mTimeStats->isEnabled());