vibrator: Switch from HIDL to AIDL
Bug: 148249136 Test: VTS, Unit Test Change-Id: Ifbcfd1358161a5643bafc6e5314311a282e70a47 Signed-off-by: Harpreet \"Eli\" Sangha <eliptus@google.com>
This commit is contained in:
51
CleanSpec.mk
Normal file
51
CleanSpec.mk
Normal file
@@ -0,0 +1,51 @@
|
||||
# Copyright 2020 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.
|
||||
#
|
||||
|
||||
# If you don't need to do a full clean build but would like to touch
|
||||
# a file or delete some intermediate files, add a clean step to the end
|
||||
# of the list. These steps will only be run once, if they haven't been
|
||||
# run before.
|
||||
#
|
||||
# E.g.:
|
||||
# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
|
||||
# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
|
||||
#
|
||||
# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
|
||||
# files that are missing or have been moved.
|
||||
#
|
||||
# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
|
||||
# Use $(OUT_DIR) to refer to the "out" directory.
|
||||
#
|
||||
# If you need to re-do something that's already mentioned, just copy
|
||||
# the command and add it to the bottom of the list. E.g., if a change
|
||||
# that you made last week required touching a file and a change you
|
||||
# made today requires touching the same file, just copy the old
|
||||
# touch step and add it to the end of the list.
|
||||
#
|
||||
# ************************************************
|
||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||
# ************************************************
|
||||
|
||||
# For example:
|
||||
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
|
||||
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
|
||||
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
|
||||
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
|
||||
|
||||
|
||||
# Vibrator HAL switch to AIDL
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.vibrator@1.3-service.bramble.rc)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.vibrator@1.3-service.bramble)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.hardware.vibrator@1.3-service.bramble.xml)
|
||||
@@ -92,7 +92,7 @@ PRODUCT_PACKAGES += \
|
||||
|
||||
# Vibrator HAL
|
||||
PRODUCT_PACKAGES += \
|
||||
android.hardware.vibrator@1.3-service.bramble
|
||||
android.hardware.vibrator-service.bramble
|
||||
|
||||
# DRV2624 Haptics Waveform
|
||||
PRODUCT_COPY_FILES += \
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
//
|
||||
// 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: "PixelVibratorDefaultsBramble",
|
||||
defaults: ["hidl_defaults"],
|
||||
relative_install_path: "hw",
|
||||
static_libs: [
|
||||
"PixelVibratorCommonBramble",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libhidlbase",
|
||||
"libcutils",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libhardware",
|
||||
"libsensorndkbridge",
|
||||
],
|
||||
proprietary: true,
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
//
|
||||
// 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_library {
|
||||
name: "PixelVibratorCommonBramble",
|
||||
srcs: [
|
||||
"HardwareBase.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"liblog",
|
||||
"libutils",
|
||||
],
|
||||
cflags: [
|
||||
"-DATRACE_TAG=(ATRACE_TAG_VIBRATOR | ATRACE_TAG_HAL)",
|
||||
"-DLOG_TAG=\"android.hardware.vibrator@1.x-common\"",
|
||||
],
|
||||
export_include_dirs: ["."],
|
||||
vendor_available: true,
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* 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 "HardwareBase.h"
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <log/log.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace common {
|
||||
namespace implementation {
|
||||
|
||||
HwApiBase::HwApiBase() {
|
||||
mPathPrefix = std::getenv("HWAPI_PATH_PREFIX") ?: "";
|
||||
if (mPathPrefix.empty()) {
|
||||
ALOGE("Failed get HWAPI path prefix!");
|
||||
}
|
||||
}
|
||||
|
||||
bool HwApiBase::has(const std::ios &stream) {
|
||||
return !!stream;
|
||||
}
|
||||
|
||||
void HwApiBase::debug(int fd) {
|
||||
dprintf(fd, "Kernel:\n");
|
||||
|
||||
for (auto &entry : utils::pathsFromEnv("HWAPI_DEBUG_PATHS", mPathPrefix)) {
|
||||
auto &path = entry.first;
|
||||
auto &stream = entry.second;
|
||||
std::string line;
|
||||
|
||||
dprintf(fd, " %s:\n", path.c_str());
|
||||
while (std::getline(stream, line)) {
|
||||
dprintf(fd, " %s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
mRecordsMutex.lock();
|
||||
dprintf(fd, " Records:\n");
|
||||
for (auto &r : mRecords) {
|
||||
if (r == nullptr) {
|
||||
continue;
|
||||
}
|
||||
dprintf(fd, " %s\n", r->toString(mNames).c_str());
|
||||
}
|
||||
mRecordsMutex.unlock();
|
||||
}
|
||||
|
||||
HwCalBase::HwCalBase() {
|
||||
std::ifstream calfile;
|
||||
auto propertyPrefix = std::getenv("PROPERTY_PREFIX");
|
||||
|
||||
if (propertyPrefix != NULL) {
|
||||
mPropertyPrefix = std::string(propertyPrefix);
|
||||
} else {
|
||||
ALOGE("Failed get property prefix!");
|
||||
}
|
||||
|
||||
utils::fileFromEnv("CALIBRATION_FILEPATH", &calfile);
|
||||
|
||||
for (std::string line; std::getline(calfile, line);) {
|
||||
if (line.empty() || line[0] == '#') {
|
||||
continue;
|
||||
}
|
||||
std::istringstream is_line(line);
|
||||
std::string key, value;
|
||||
if (std::getline(is_line, key, ':') && std::getline(is_line, value)) {
|
||||
mCalData[utils::trim(key)] = utils::trim(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HwCalBase::debug(int fd) {
|
||||
std::ifstream stream;
|
||||
std::string path;
|
||||
std::string line;
|
||||
struct context {
|
||||
HwCalBase *obj;
|
||||
int fd;
|
||||
} context{this, fd};
|
||||
|
||||
dprintf(fd, "Properties:\n");
|
||||
|
||||
property_list(
|
||||
[](const char *key, const char *value, void *cookie) {
|
||||
struct context *context = static_cast<struct context *>(cookie);
|
||||
HwCalBase *obj = context->obj;
|
||||
int fd = context->fd;
|
||||
const std::string expect{obj->mPropertyPrefix};
|
||||
const std::string actual{key, std::min(strlen(key), expect.size())};
|
||||
if (actual == expect) {
|
||||
dprintf(fd, " %s:\n", key);
|
||||
dprintf(fd, " %s\n", value);
|
||||
}
|
||||
},
|
||||
&context);
|
||||
|
||||
dprintf(fd, "\n");
|
||||
|
||||
dprintf(fd, "Persist:\n");
|
||||
|
||||
utils::fileFromEnv("CALIBRATION_FILEPATH", &stream, &path);
|
||||
|
||||
dprintf(fd, " %s:\n", path.c_str());
|
||||
while (std::getline(stream, line)) {
|
||||
dprintf(fd, " %s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace common
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* 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 ANDROID_HARDWARE_VIBRATOR_HARDWARE_BASE_H
|
||||
#define ANDROID_HARDWARE_VIBRATOR_HARDWARE_BASE_H
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <log/log.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <utils/Trace.h>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace common {
|
||||
namespace implementation {
|
||||
|
||||
using base::unique_fd;
|
||||
|
||||
class HwApiBase {
|
||||
private:
|
||||
using NamesMap = std::map<const std::ios *, std::string>;
|
||||
|
||||
class RecordInterface {
|
||||
public:
|
||||
virtual std::string toString(const NamesMap &names) = 0;
|
||||
virtual ~RecordInterface() {}
|
||||
};
|
||||
template <typename T>
|
||||
class Record : public RecordInterface {
|
||||
public:
|
||||
Record(const char *func, const T &value, const std::ios *stream)
|
||||
: mFunc(func), mValue(value), mStream(stream) {}
|
||||
std::string toString(const NamesMap &names) override;
|
||||
|
||||
private:
|
||||
const char *mFunc;
|
||||
const T mValue;
|
||||
const std::ios *mStream;
|
||||
};
|
||||
using Records = std::list<std::unique_ptr<RecordInterface>>;
|
||||
|
||||
static constexpr uint32_t RECORDS_SIZE = 32;
|
||||
|
||||
public:
|
||||
HwApiBase();
|
||||
void debug(int fd);
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
void open(const std::string &name, T *stream);
|
||||
template <typename T>
|
||||
void openFull(const std::string &name, T *stream);
|
||||
bool has(const std::ios &stream);
|
||||
template <typename T>
|
||||
bool get(T *value, std::istream *stream);
|
||||
template <typename T>
|
||||
bool set(const T &value, std::ostream *stream);
|
||||
template <typename T>
|
||||
bool poll(const T &value, std::istream *stream);
|
||||
template <typename T>
|
||||
void record(const char *func, const T &value, const std::ios *stream);
|
||||
|
||||
private:
|
||||
std::string mPathPrefix;
|
||||
NamesMap mNames;
|
||||
Records mRecords{RECORDS_SIZE};
|
||||
std::mutex mRecordsMutex;
|
||||
};
|
||||
|
||||
#define HWAPI_RECORD(args...) HwApiBase::record(__FUNCTION__, ##args)
|
||||
|
||||
template <typename T>
|
||||
void HwApiBase::open(const std::string &name, T *stream) {
|
||||
mNames[stream] = name;
|
||||
utils::openNoCreate(mPathPrefix + name, stream);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void HwApiBase::openFull(const std::string &name, T *stream) {
|
||||
mNames[stream] = name;
|
||||
utils::openNoCreate(name, stream);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HwApiBase::get(T *value, std::istream *stream) {
|
||||
ATRACE_NAME("HwApi::get");
|
||||
bool ret;
|
||||
stream->seekg(0);
|
||||
*stream >> *value;
|
||||
if (!(ret = !!*stream)) {
|
||||
ALOGE("Failed to read %s (%d): %s", mNames[stream].c_str(), errno, strerror(errno));
|
||||
}
|
||||
stream->clear();
|
||||
HWAPI_RECORD(*value, stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HwApiBase::set(const T &value, std::ostream *stream) {
|
||||
ATRACE_NAME("HwApi::set");
|
||||
using utils::operator<<;
|
||||
bool ret;
|
||||
*stream << value << std::endl;
|
||||
if (!(ret = !!*stream)) {
|
||||
ALOGE("Failed to write %s (%d): %s", mNames[stream].c_str(), errno, strerror(errno));
|
||||
stream->clear();
|
||||
}
|
||||
HWAPI_RECORD(value, stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HwApiBase::poll(const T &value, std::istream *stream) {
|
||||
ATRACE_NAME("HwApi::poll");
|
||||
auto path = mPathPrefix + mNames[stream];
|
||||
unique_fd fileFd{::open(path.c_str(), O_RDONLY)};
|
||||
unique_fd epollFd{epoll_create(1)};
|
||||
epoll_event event = {
|
||||
.events = EPOLLPRI | EPOLLET,
|
||||
};
|
||||
T actual;
|
||||
bool ret;
|
||||
|
||||
if (epoll_ctl(epollFd, EPOLL_CTL_ADD, fileFd, &event)) {
|
||||
ALOGE("Failed to poll %s (%d): %s", mNames[stream].c_str(), errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
while ((ret = get(&actual, stream)) && (actual != value)) {
|
||||
epoll_wait(epollFd, &event, 1, -1);
|
||||
}
|
||||
|
||||
HWAPI_RECORD(value, stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void HwApiBase::record(const char *func, const T &value, const std::ios *stream) {
|
||||
std::lock_guard<std::mutex> lock(mRecordsMutex);
|
||||
mRecords.emplace_back(std::make_unique<Record<T>>(func, value, stream));
|
||||
mRecords.pop_front();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string HwApiBase::Record<T>::toString(const NamesMap &names) {
|
||||
using utils::operator<<;
|
||||
std::stringstream ret;
|
||||
|
||||
ret << mFunc << " '" << names.at(mStream) << "' = '" << mValue << "'";
|
||||
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
class HwCalBase {
|
||||
public:
|
||||
HwCalBase();
|
||||
void debug(int fd);
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
bool getProperty(const char *key, T *value, const T defval);
|
||||
template <typename T>
|
||||
bool getPersist(const char *key, T *value);
|
||||
|
||||
private:
|
||||
std::string mPropertyPrefix;
|
||||
std::map<std::string, std::string> mCalData;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool HwCalBase::getProperty(const char *key, T *outval, const T defval) {
|
||||
ATRACE_NAME("HwCal::getProperty");
|
||||
*outval = utils::getProperty(mPropertyPrefix + key, defval);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HwCalBase::getPersist(const char *key, T *value) {
|
||||
ATRACE_NAME("HwCal::getPersist");
|
||||
auto it = mCalData.find(key);
|
||||
if (it == mCalData.end()) {
|
||||
ALOGE("Missing %s config!", key);
|
||||
return false;
|
||||
}
|
||||
std::stringstream stream{it->second};
|
||||
utils::unpack(stream, value);
|
||||
if (!stream || !stream.eof()) {
|
||||
ALOGE("Invalid %s config!", key);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace common
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_VIBRATOR_HARDWARE_BASE_H
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"postsubmit": [
|
||||
{
|
||||
"name": "VibratorHalIntegrationBenchmarkBramble"
|
||||
},
|
||||
{
|
||||
"name": "VibratorHalIntegrationBenchmarkBramble",
|
||||
"keywords": [
|
||||
"primary-device"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
//
|
||||
// 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_benchmark {
|
||||
name: "VibratorHalIntegrationBenchmarkBramble",
|
||||
defaults: ["hidl_defaults"],
|
||||
srcs: [
|
||||
"benchmark.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.vibrator@1.0",
|
||||
"android.hardware.vibrator@1.1",
|
||||
"android.hardware.vibrator@1.2",
|
||||
"android.hardware.vibrator@1.3",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libutils",
|
||||
],
|
||||
test_suites: ["device-tests"],
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* 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 "benchmark/benchmark.h"
|
||||
|
||||
#include <android/hardware/vibrator/1.3/IVibrator.h>
|
||||
|
||||
using ::android::sp;
|
||||
using ::android::hardware::hidl_enum_range;
|
||||
using ::android::hardware::Return;
|
||||
using ::android::hardware::details::hidl_enum_values;
|
||||
using ::benchmark::Counter;
|
||||
using ::benchmark::Fixture;
|
||||
using ::benchmark::kMicrosecond;
|
||||
using ::benchmark::State;
|
||||
using ::benchmark::internal::Benchmark;
|
||||
using ::std::chrono::duration;
|
||||
using ::std::chrono::duration_cast;
|
||||
using ::std::chrono::high_resolution_clock;
|
||||
|
||||
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;
|
||||
|
||||
template <typename I>
|
||||
class VibratorBench : public Fixture {
|
||||
public:
|
||||
void SetUp(State & /*state*/) override { mVibrator = I::getService(); }
|
||||
|
||||
void TearDown(State & /*state*/) override {
|
||||
if (!mVibrator) {
|
||||
return;
|
||||
}
|
||||
mVibrator->off();
|
||||
}
|
||||
|
||||
static void DefaultConfig(Benchmark *b) { b->Unit(kMicrosecond); }
|
||||
|
||||
static void DefaultArgs(Benchmark * /*b*/) {
|
||||
// none
|
||||
}
|
||||
|
||||
protected:
|
||||
auto getOtherArg(const State &state, std::size_t index) const {
|
||||
return state.range(index + 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
sp<I> mVibrator;
|
||||
};
|
||||
|
||||
enum class EmptyEnum : uint32_t;
|
||||
template <>
|
||||
inline constexpr std::array<EmptyEnum, 0> hidl_enum_values<EmptyEnum> = {};
|
||||
|
||||
template <typename T, typename U>
|
||||
std::set<T> difference(const hidl_enum_range<T> &t, const hidl_enum_range<U> &u) {
|
||||
class Compare {
|
||||
public:
|
||||
bool operator()(const T &a, const U &b) { return a < static_cast<T>(b); }
|
||||
bool operator()(const U &a, const T &b) { return static_cast<T>(a) < b; }
|
||||
};
|
||||
std::set<T> ret;
|
||||
|
||||
std::set_difference(t.begin(), t.end(), u.begin(), u.end(),
|
||||
std::insert_iterator<decltype(ret)>(ret, ret.begin()), Compare());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename I, typename E1, typename E2 = EmptyEnum>
|
||||
class VibratorEffectsBench : public VibratorBench<I> {
|
||||
public:
|
||||
using Effect = E1;
|
||||
using EffectStrength = V1_0::EffectStrength;
|
||||
using Status = V1_0::Status;
|
||||
|
||||
public:
|
||||
static void DefaultArgs(Benchmark *b) {
|
||||
b->ArgNames({"Effect", "Strength"});
|
||||
for (const auto &effect : difference(hidl_enum_range<E1>(), hidl_enum_range<E2>())) {
|
||||
for (const auto &strength : hidl_enum_range<EffectStrength>()) {
|
||||
b->Args({static_cast<long>(effect), static_cast<long>(strength)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void performBench(State *state, Return<void> (I::*performApi)(Effect, EffectStrength,
|
||||
typename I::perform_cb)) {
|
||||
auto effect = getEffect(*state);
|
||||
auto strength = getStrength(*state);
|
||||
bool supported = true;
|
||||
|
||||
(*this->mVibrator.*performApi)(effect, strength, [&](Status status, uint32_t /*lengthMs*/) {
|
||||
if (status == Status::UNSUPPORTED_OPERATION) {
|
||||
supported = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto _ : *state) {
|
||||
state->ResumeTiming();
|
||||
(*this->mVibrator.*performApi)(effect, strength,
|
||||
[](Status /*status*/, uint32_t /*lengthMs*/) {});
|
||||
state->PauseTiming();
|
||||
this->mVibrator->off();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
auto getEffect(const State &state) const {
|
||||
return static_cast<Effect>(this->getOtherArg(state, 0));
|
||||
}
|
||||
|
||||
auto getStrength(const State &state) const {
|
||||
return static_cast<EffectStrength>(this->getOtherArg(state, 1));
|
||||
}
|
||||
};
|
||||
|
||||
#define BENCHMARK_WRAPPER(fixt, test, code) \
|
||||
BENCHMARK_DEFINE_F(fixt, test) \
|
||||
/* NOLINTNEXTLINE */ \
|
||||
(State & state) { \
|
||||
if (!mVibrator) { \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
code \
|
||||
} \
|
||||
BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultConfig)->Apply(fixt::DefaultArgs)
|
||||
|
||||
using VibratorBench_V1_0 = VibratorBench<V1_0::IVibrator>;
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench_V1_0, on, {
|
||||
uint32_t ms = UINT32_MAX;
|
||||
|
||||
for (auto _ : state) {
|
||||
state.ResumeTiming();
|
||||
mVibrator->on(ms);
|
||||
state.PauseTiming();
|
||||
mVibrator->off();
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench_V1_0, off, {
|
||||
uint32_t ms = UINT32_MAX;
|
||||
|
||||
for (auto _ : state) {
|
||||
state.PauseTiming();
|
||||
mVibrator->on(ms);
|
||||
state.ResumeTiming();
|
||||
mVibrator->off();
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, {
|
||||
for (auto _ : state) {
|
||||
mVibrator->supportsAmplitudeControl();
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, {
|
||||
uint8_t amplitude = UINT8_MAX;
|
||||
|
||||
if (!mVibrator->supportsAmplitudeControl()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mVibrator->on(UINT32_MAX);
|
||||
|
||||
for (auto _ : state) {
|
||||
mVibrator->setAmplitude(amplitude);
|
||||
}
|
||||
|
||||
mVibrator->off();
|
||||
});
|
||||
|
||||
using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>;
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorEffectsBench_V1_0, perform,
|
||||
{ performBench(&state, &V1_0::IVibrator::perform); });
|
||||
|
||||
using VibratorEffectsBench_V1_1 =
|
||||
VibratorEffectsBench<V1_1::IVibrator, V1_1::Effect_1_1, V1_0::Effect>;
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorEffectsBench_V1_1, perform_1_1,
|
||||
{ performBench(&state, &V1_1::IVibrator::perform_1_1); });
|
||||
|
||||
using VibratorEffectsBench_V1_2 =
|
||||
VibratorEffectsBench<V1_2::IVibrator, V1_2::Effect, V1_1::Effect_1_1>;
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2,
|
||||
{ performBench(&state, &V1_2::IVibrator::perform_1_2); });
|
||||
|
||||
using VibratorBench_V1_3 = VibratorBench<V1_3::IVibrator>;
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, {
|
||||
for (auto _ : state) {
|
||||
mVibrator->supportsExternalControl();
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, {
|
||||
bool enable = true;
|
||||
|
||||
if (!mVibrator->supportsExternalControl()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto _ : state) {
|
||||
state.ResumeTiming();
|
||||
mVibrator->setExternalControl(enable);
|
||||
state.PauseTiming();
|
||||
mVibrator->setExternalControl(false);
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, {
|
||||
if (!mVibrator->supportsExternalControl()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mVibrator->setExternalControl(true);
|
||||
|
||||
for (auto _ : state) {
|
||||
mVibrator->supportsAmplitudeControl();
|
||||
}
|
||||
|
||||
mVibrator->setExternalControl(false);
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, {
|
||||
uint8_t amplitude = UINT8_MAX;
|
||||
|
||||
if (!mVibrator->supportsExternalControl()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mVibrator->setExternalControl(true);
|
||||
|
||||
if (!mVibrator->supportsAmplitudeControl()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto _ : state) {
|
||||
mVibrator->setAmplitude(amplitude);
|
||||
}
|
||||
|
||||
mVibrator->setExternalControl(false);
|
||||
});
|
||||
|
||||
using VibratorEffectsBench_V1_3 = VibratorEffectsBench<V1_3::IVibrator, V1_3::Effect, V1_2::Effect>;
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3,
|
||||
{ performBench(&state, &V1_3::IVibrator::perform_1_3); });
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* 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 ANDROID_HARDWARE_VIBRATOR_UTILS_H
|
||||
#define ANDROID_HARDWARE_VIBRATOR_UTILS_H
|
||||
|
||||
#include <android-base/macros.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <log/log.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace utils {
|
||||
|
||||
template <typename T>
|
||||
class Is_Iterable {
|
||||
private:
|
||||
template <typename U>
|
||||
static std::true_type test(typename U::iterator *u);
|
||||
|
||||
template <typename U>
|
||||
static std::false_type test(U *u);
|
||||
|
||||
public:
|
||||
static const bool value = decltype(test<T>(0))::value;
|
||||
};
|
||||
|
||||
template <typename T, bool B>
|
||||
using Enable_If_Iterable = std::enable_if_t<Is_Iterable<T>::value == B>;
|
||||
|
||||
template <typename T, typename U = void>
|
||||
using Enable_If_Signed = std::enable_if_t<std::is_signed_v<T>, U>;
|
||||
|
||||
template <typename T, typename U = void>
|
||||
using Enable_If_Unsigned = std::enable_if_t<std::is_unsigned_v<T>, U>;
|
||||
|
||||
// override for default behavior of printing as a character
|
||||
inline std::ostream &operator<<(std::ostream &stream, const int8_t value) {
|
||||
return stream << +value;
|
||||
}
|
||||
// override for default behavior of printing as a character
|
||||
inline std::ostream &operator<<(std::ostream &stream, const uint8_t value) {
|
||||
return stream << +value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline auto toUnderlying(const T value) {
|
||||
return static_cast<std::underlying_type_t<T>>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Enable_If_Iterable<T, true> unpack(std::istream &stream, T *value) {
|
||||
for (auto &entry : *value) {
|
||||
stream >> entry;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Enable_If_Iterable<T, false> unpack(std::istream &stream, T *value) {
|
||||
stream >> *value;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void unpack<std::string>(std::istream &stream, std::string *value) {
|
||||
*value = std::string(std::istreambuf_iterator(stream), {});
|
||||
stream.setstate(std::istream::eofbit);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Enable_If_Signed<T, T> getProperty(const std::string &key, const T def) {
|
||||
return base::GetIntProperty(key, def);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Enable_If_Unsigned<T, T> getProperty(const std::string &key, const T def) {
|
||||
return base::GetUintProperty(key, def);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool getProperty<bool>(const std::string &key, const bool def) {
|
||||
return base::GetBoolProperty(key, def);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void openNoCreate(const std::string &file, T *outStream) {
|
||||
auto mode = std::is_base_of_v<std::ostream, T> ? std::ios_base::out : std::ios_base::in;
|
||||
|
||||
// Force 'in' mode to prevent file creation
|
||||
outStream->open(file, mode | std::ios_base::in);
|
||||
if (!*outStream) {
|
||||
ALOGE("Failed to open %s (%d): %s", file.c_str(), errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void fileFromEnv(const char *env, T *outStream, std::string *outName = nullptr) {
|
||||
auto file = std::getenv(env);
|
||||
|
||||
if (file == nullptr) {
|
||||
ALOGE("Failed get env %s", env);
|
||||
return;
|
||||
}
|
||||
|
||||
if (outName != nullptr) {
|
||||
*outName = std::string(file);
|
||||
}
|
||||
|
||||
openNoCreate(file, outStream);
|
||||
}
|
||||
|
||||
static ATTRIBUTE_UNUSED auto pathsFromEnv(const char *env, const std::string &prefix = "") {
|
||||
std::map<std::string, std::ifstream> ret;
|
||||
auto value = std::getenv(env);
|
||||
|
||||
if (value == nullptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::istringstream paths{value};
|
||||
std::string path;
|
||||
|
||||
while (paths >> path) {
|
||||
ret[path].open(prefix + path);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ATTRIBUTE_UNUSED std::string trim(const std::string &str,
|
||||
const std::string &whitespace = " \t") {
|
||||
const auto str_begin = str.find_first_not_of(whitespace);
|
||||
if (str_begin == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const auto str_end = str.find_last_not_of(whitespace);
|
||||
const auto str_range = str_end - str_begin + 1;
|
||||
|
||||
return str.substr(str_begin, str_range);
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_VIBRATOR_UTILS_H
|
||||
@@ -14,33 +14,46 @@
|
||||
// limitations under the License.
|
||||
|
||||
cc_defaults {
|
||||
name: "android.hardware.vibrator@1.3-defaults.bramble",
|
||||
defaults: ["PixelVibratorDefaultsBramble"],
|
||||
shared_libs: [
|
||||
"android.hardware.vibrator@1.0",
|
||||
"android.hardware.vibrator@1.1",
|
||||
"android.hardware.vibrator@1.2",
|
||||
"android.hardware.vibrator@1.3",
|
||||
],
|
||||
name: "android.hardware.vibrator-defaults.bramble",
|
||||
cflags: [
|
||||
"-DATRACE_TAG=(ATRACE_TAG_VIBRATOR | ATRACE_TAG_HAL)",
|
||||
"-DLOG_TAG=\"android.hardware.vibrator@1.3-bramble\"",
|
||||
"-DLOG_TAG=\"android.hardware.vibrator-bramble\"",
|
||||
],
|
||||
}
|
||||
|
||||
cc_defaults {
|
||||
name: "VibratorHalDrv2624BinaryDefaultsBramble",
|
||||
defaults: [
|
||||
"PixelVibratorBinaryDefaults",
|
||||
"android.hardware.vibrator-defaults.bramble",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
// TODO: Add sensor stub for tests.
|
||||
},
|
||||
vendor: {
|
||||
shared_libs: [
|
||||
"libsensorndkbridge",
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "android.hardware.vibrator@1.3-impl.bramble",
|
||||
defaults: ["android.hardware.vibrator@1.3-defaults.bramble"],
|
||||
name: "android.hardware.vibrator-impl.bramble",
|
||||
defaults: ["VibratorHalDrv2624BinaryDefaultsBramble"],
|
||||
srcs: ["Vibrator.cpp"],
|
||||
export_include_dirs: ["."],
|
||||
proprietary: true,
|
||||
visibility: [":__subpackages__"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.vibrator@1.3-service.bramble",
|
||||
defaults: ["android.hardware.vibrator@1.3-defaults.bramble"],
|
||||
init_rc: ["android.hardware.vibrator@1.3-service.bramble.rc"],
|
||||
vintf_fragments: ["android.hardware.vibrator@1.3-service.bramble.xml"],
|
||||
name: "android.hardware.vibrator-service.bramble",
|
||||
defaults: ["VibratorHalDrv2624BinaryDefaultsBramble"],
|
||||
init_rc: ["android.hardware.vibrator-service.bramble.rc"],
|
||||
vintf_fragments: ["android.hardware.vibrator-service.bramble.xml"],
|
||||
srcs: ["service.cpp"],
|
||||
static_libs: ["android.hardware.vibrator@1.3-impl.bramble"],
|
||||
static_libs: ["android.hardware.vibrator-impl.bramble"],
|
||||
proprietary: true,
|
||||
}
|
||||
|
||||
@@ -13,20 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_VIBRATOR_HARDWARE_H
|
||||
#define ANDROID_HARDWARE_VIBRATOR_HARDWARE_H
|
||||
#pragma once
|
||||
|
||||
#include "../common/HardwareBase.h"
|
||||
#include "Vibrator.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace V1_3 {
|
||||
namespace implementation {
|
||||
|
||||
using common::implementation::HwApiBase;
|
||||
using common::implementation::HwCalBase;
|
||||
|
||||
class HwApi : public Vibrator::HwApi, private HwApiBase {
|
||||
public:
|
||||
@@ -76,6 +71,12 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
|
||||
openFull("/sys/devices/virtual/thermal/tz-by-name/rf-front-therm/temp", &mPATemp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void openFull(const std::string &name, T *stream) {
|
||||
saveName(name, stream);
|
||||
utils::openNoCreate(name, stream);
|
||||
}
|
||||
|
||||
private:
|
||||
std::ofstream mAutocal;
|
||||
std::ofstream mOlLraPeriod;
|
||||
@@ -181,10 +182,7 @@ class HwCal : public Vibrator::HwCal, private HwCalBase {
|
||||
void debug(int fd) override { HwCalBase::debug(fd); }
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_3
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_VIBRATOR_HARDWARE_H
|
||||
} // namespace aidl
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "Vibrator.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <android/looper.h>
|
||||
#include <android/sensor.h>
|
||||
@@ -22,6 +23,7 @@
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/vibrator.h>
|
||||
#include <log/log.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Trace.h>
|
||||
|
||||
#include <cinttypes>
|
||||
@@ -30,13 +32,13 @@
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace V1_3 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::NO_ERROR;
|
||||
using ::android::UNEXPECTED_NULL;
|
||||
|
||||
static constexpr int8_t MAX_RTP_INPUT = 127;
|
||||
static constexpr int8_t MIN_RTP_INPUT = 0;
|
||||
@@ -272,9 +274,6 @@ static bool motionAwareness() {
|
||||
|
||||
using utils::toUnderlying;
|
||||
|
||||
using Status = ::android::hardware::vibrator::V1_0::Status;
|
||||
using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength;
|
||||
|
||||
Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal)
|
||||
: mHwApi(std::move(hwapi)), mHwCal(std::move(hwcal)) {
|
||||
std::string autocal;
|
||||
@@ -385,9 +384,19 @@ Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal)
|
||||
}
|
||||
}
|
||||
|
||||
Return<Status> Vibrator::on(uint32_t timeoutMs, const char mode[],
|
||||
const std::unique_ptr<VibrationConfig> &config,
|
||||
const int8_t volOffset) {
|
||||
ndk::ScopedAStatus Vibrator::getCapabilities(int32_t *_aidl_return) {
|
||||
ATRACE_NAME("Vibrator::getCapabilities");
|
||||
int32_t ret = 0;
|
||||
if (mHwApi->hasRtpInput()) {
|
||||
ret |= IVibrator::CAP_AMPLITUDE_CONTROL;
|
||||
}
|
||||
*_aidl_return = ret;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, const char mode[],
|
||||
const std::unique_ptr<VibrationConfig> &config,
|
||||
const int8_t volOffset) {
|
||||
LoopControl loopMode = LoopControl::OPEN;
|
||||
|
||||
// Open-loop mode is used for short click for over-drive
|
||||
@@ -399,7 +408,7 @@ Return<Status> Vibrator::on(uint32_t timeoutMs, const char mode[],
|
||||
mHwApi->setCtrlLoop(toUnderlying(loopMode));
|
||||
if (!mHwApi->setDuration(timeoutMs)) {
|
||||
ALOGE("Failed to set duration (%d): %s", errno, strerror(errno));
|
||||
return Status::UNKNOWN_ERROR;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
|
||||
mHwApi->setMode(mode);
|
||||
@@ -411,15 +420,20 @@ Return<Status> Vibrator::on(uint32_t timeoutMs, const char mode[],
|
||||
|
||||
if (!mHwApi->setActivate(1)) {
|
||||
ALOGE("Failed to activate (%d): %s", errno, strerror(errno));
|
||||
return Status::UNKNOWN_ERROR;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
|
||||
return Status::OK;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::vibrator::V1_2::IVibrator follow.
|
||||
Return<Status> Vibrator::on(uint32_t timeoutMs) {
|
||||
ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
|
||||
const std::shared_ptr<IVibratorCallback> &callback) {
|
||||
ATRACE_NAME("Vibrator::on");
|
||||
|
||||
if (callback) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
if (mDynamicConfig) {
|
||||
int temperature = 0;
|
||||
mHwApi->getPATemp(&temperature);
|
||||
@@ -438,62 +452,47 @@ Return<Status> Vibrator::on(uint32_t timeoutMs) {
|
||||
return on(timeoutMs, RTP_MODE, mSteadyConfig, 0);
|
||||
}
|
||||
|
||||
Return<Status> Vibrator::off() {
|
||||
ndk::ScopedAStatus Vibrator::off() {
|
||||
ATRACE_NAME("Vibrator::off");
|
||||
if (!mHwApi->setActivate(0)) {
|
||||
ALOGE("Failed to turn vibrator off (%d): %s", errno, strerror(errno));
|
||||
return Status::UNKNOWN_ERROR;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
return Status::OK;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
Return<bool> Vibrator::supportsAmplitudeControl() {
|
||||
ATRACE_NAME("Vibrator::supportsAmplitudeControl");
|
||||
return (mHwApi->hasRtpInput() ? true : false);
|
||||
}
|
||||
|
||||
Return<Status> Vibrator::setAmplitude(uint8_t amplitude) {
|
||||
ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
|
||||
ATRACE_NAME("Vibrator::setAmplitude");
|
||||
if (amplitude == 0) {
|
||||
return Status::BAD_VALUE;
|
||||
if (amplitude <= 0.0f || amplitude > 1.0f) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
|
||||
int32_t rtp_input =
|
||||
std::round((amplitude - 1) / 254.0 * (MAX_RTP_INPUT - MIN_RTP_INPUT) + MIN_RTP_INPUT);
|
||||
int32_t rtp_input = std::round(amplitude * (MAX_RTP_INPUT - MIN_RTP_INPUT) + MIN_RTP_INPUT);
|
||||
|
||||
if (!mHwApi->setRtpInput(rtp_input)) {
|
||||
ALOGE("Failed to set amplitude (%d): %s", errno, strerror(errno));
|
||||
return Status::UNKNOWN_ERROR;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
|
||||
return Status::OK;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::vibrator::V1_3::IVibrator follow.
|
||||
|
||||
Return<bool> Vibrator::supportsExternalControl() {
|
||||
ATRACE_NAME("Vibrator::supportsExternalControl");
|
||||
return false;
|
||||
}
|
||||
|
||||
Return<Status> Vibrator::setExternalControl(bool enabled) {
|
||||
ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
|
||||
ATRACE_NAME("Vibrator::setExternalControl");
|
||||
ALOGE("Not support in DRV2624 solution, %d", enabled);
|
||||
return Status::UNSUPPORTED_OPERATION;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
// Methods from ::android.hidl.base::V1_0::IBase follow.
|
||||
|
||||
Return<void> Vibrator::debug(const hidl_handle &handle,
|
||||
const hidl_vec<hidl_string> & /* options */) {
|
||||
if (handle == nullptr || handle->numFds < 1 || handle->data[0] < 0) {
|
||||
binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
|
||||
if (fd < 0) {
|
||||
ALOGE("Called debug() with invalid fd.");
|
||||
return Void();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
int fd = handle->data[0];
|
||||
(void)args;
|
||||
(void)numArgs;
|
||||
|
||||
dprintf(fd, "HIDL:\n");
|
||||
dprintf(fd, "AIDL:\n");
|
||||
|
||||
dprintf(fd, " Close Loop Thresh: %" PRIu32 "\n", mCloseLoopThreshold);
|
||||
if (mSteadyConfig) {
|
||||
@@ -524,45 +523,33 @@ Return<void> Vibrator::debug(const hidl_handle &handle,
|
||||
mHwCal->debug(fd);
|
||||
|
||||
fsync(fd);
|
||||
return Void();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
Return<void> Vibrator::perform(V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
|
||||
return performWrapper(effect, strength, _hidl_cb);
|
||||
ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect> *_aidl_return) {
|
||||
*_aidl_return = {Effect::TEXTURE_TICK, Effect::TICK, Effect::CLICK, Effect::HEAVY_CLICK,
|
||||
Effect::DOUBLE_CLICK};
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
Return<void> Vibrator::perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength,
|
||||
perform_cb _hidl_cb) {
|
||||
return performWrapper(effect, strength, _hidl_cb);
|
||||
}
|
||||
ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
|
||||
const std::shared_ptr<IVibratorCallback> &callback,
|
||||
int32_t *_aidl_return) {
|
||||
ATRACE_NAME("Vibrator::perform");
|
||||
ndk::ScopedAStatus status;
|
||||
|
||||
Return<void> Vibrator::perform_1_2(V1_2::Effect effect, EffectStrength strength,
|
||||
perform_cb _hidl_cb) {
|
||||
return performWrapper(effect, strength, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> Vibrator::perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
|
||||
return performWrapper(effect, strength, _hidl_cb);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Return<void> Vibrator::performWrapper(T effect, EffectStrength strength, perform_cb _hidl_cb) {
|
||||
ATRACE_NAME("Vibrator::performWrapper");
|
||||
auto validEffectRange = hidl_enum_range<T>();
|
||||
if (effect < *validEffectRange.begin() || effect > *std::prev(validEffectRange.end())) {
|
||||
_hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
|
||||
return Void();
|
||||
if (callback) {
|
||||
status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
} else {
|
||||
status = performEffect(effect, strength, _aidl_return);
|
||||
}
|
||||
auto validStrengthRange = hidl_enum_range<EffectStrength>();
|
||||
if (strength < *validStrengthRange.begin() || strength > *std::prev(validStrengthRange.end())) {
|
||||
_hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
|
||||
return Void();
|
||||
}
|
||||
return performEffect(static_cast<Effect>(effect), strength, _hidl_cb);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Return<void> Vibrator::performEffect(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
|
||||
Status status = Status::OK;
|
||||
ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strength,
|
||||
int32_t *outTimeMs) {
|
||||
ndk::ScopedAStatus status;
|
||||
uint32_t timeMS;
|
||||
int8_t volOffset;
|
||||
|
||||
@@ -577,7 +564,7 @@ Return<void> Vibrator::performEffect(Effect effect, EffectStrength strength, per
|
||||
volOffset = 1;
|
||||
break;
|
||||
default:
|
||||
status = Status::UNSUPPORTED_OPERATION;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -608,16 +595,53 @@ Return<void> Vibrator::performEffect(Effect effect, EffectStrength strength, per
|
||||
volOffset += HEAVY_CLICK;
|
||||
break;
|
||||
default:
|
||||
_hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
|
||||
return Void();
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
on(timeMS, WAVEFORM_MODE, mEffectConfig, volOffset);
|
||||
_hidl_cb(status, timeMS);
|
||||
return Void();
|
||||
status = on(timeMS, WAVEFORM_MODE, mEffectConfig, volOffset);
|
||||
if (!status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
*outTimeMs = timeMS;
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect> * /*_aidl_return*/) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t /*id*/, Effect /*effect*/,
|
||||
EffectStrength /*strength*/) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t /*id*/) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t * /*maxDelayMs*/) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t * /*maxSize*/) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive> * /*supported*/) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive /*primitive*/,
|
||||
int32_t * /*durationMs*/) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect> & /*composite*/,
|
||||
const std::shared_ptr<IVibratorCallback> & /*callback*/) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_3
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
|
||||
@@ -13,21 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_VIBRATOR_V1_3_VIBRATOR_H
|
||||
#define ANDROID_HARDWARE_VIBRATOR_V1_3_VIBRATOR_H
|
||||
#pragma once
|
||||
|
||||
#include <android/hardware/vibrator/1.3/IVibrator.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <aidl/android/hardware/vibrator/BnVibrator.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace V1_3 {
|
||||
namespace implementation {
|
||||
|
||||
class Vibrator : public IVibrator {
|
||||
class Vibrator : public BnVibrator {
|
||||
public:
|
||||
// APIs for interfacing with the kernel driver.
|
||||
class HwApi {
|
||||
@@ -156,35 +153,34 @@ class Vibrator : public IVibrator {
|
||||
public:
|
||||
Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal);
|
||||
|
||||
// Methods from ::android::hardware::vibrator::V1_0::IVibrator follow.
|
||||
using Status = ::android::hardware::vibrator::V1_0::Status;
|
||||
Return<Status> on(uint32_t timeoutMs) override;
|
||||
Return<Status> off() override;
|
||||
Return<bool> supportsAmplitudeControl() override;
|
||||
Return<Status> setAmplitude(uint8_t amplitude) override;
|
||||
ndk::ScopedAStatus getCapabilities(int32_t *_aidl_return) override;
|
||||
ndk::ScopedAStatus off() override;
|
||||
ndk::ScopedAStatus on(int32_t timeoutMs,
|
||||
const std::shared_ptr<IVibratorCallback> &callback) override;
|
||||
ndk::ScopedAStatus perform(Effect effect, EffectStrength strength,
|
||||
const std::shared_ptr<IVibratorCallback> &callback,
|
||||
int32_t *_aidl_return) override;
|
||||
ndk::ScopedAStatus getSupportedEffects(std::vector<Effect> *_aidl_return) override;
|
||||
ndk::ScopedAStatus setAmplitude(float amplitude) override;
|
||||
ndk::ScopedAStatus setExternalControl(bool enabled) override;
|
||||
ndk::ScopedAStatus getCompositionDelayMax(int32_t *maxDelayMs);
|
||||
ndk::ScopedAStatus getCompositionSizeMax(int32_t *maxSize);
|
||||
ndk::ScopedAStatus getSupportedPrimitives(std::vector<CompositePrimitive> *supported) override;
|
||||
ndk::ScopedAStatus getPrimitiveDuration(CompositePrimitive primitive,
|
||||
int32_t *durationMs) override;
|
||||
ndk::ScopedAStatus compose(const std::vector<CompositeEffect> &composite,
|
||||
const std::shared_ptr<IVibratorCallback> &callback) override;
|
||||
ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector<Effect> *_aidl_return) override;
|
||||
ndk::ScopedAStatus alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) override;
|
||||
ndk::ScopedAStatus alwaysOnDisable(int32_t id) override;
|
||||
|
||||
// Methods from ::android::hardware::vibrator::V1_3::IVibrator follow.
|
||||
Return<bool> supportsExternalControl() override;
|
||||
Return<Status> setExternalControl(bool enabled) override;
|
||||
|
||||
using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength;
|
||||
Return<void> perform(V1_0::Effect effect, EffectStrength strength,
|
||||
perform_cb _hidl_cb) override;
|
||||
Return<void> perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength,
|
||||
perform_cb _hidl_cb) override;
|
||||
Return<void> perform_1_2(V1_2::Effect effect, EffectStrength strength,
|
||||
perform_cb _hidl_cb) override;
|
||||
Return<void> perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) override;
|
||||
|
||||
// Methods from ::android.hidl.base::V1_0::IBase follow.
|
||||
Return<void> debug(const hidl_handle &handle, const hidl_vec<hidl_string> &options) override;
|
||||
binder_status_t dump(int fd, const char **args, uint32_t numArgs) override;
|
||||
|
||||
private:
|
||||
Return<Status> on(uint32_t timeoutMs, const char mode[],
|
||||
const std::unique_ptr<VibrationConfig> &config, const int8_t volOffset);
|
||||
template <typename T>
|
||||
Return<void> performWrapper(T effect, EffectStrength strength, perform_cb _hidl_cb);
|
||||
Return<void> performEffect(Effect effect, EffectStrength strength, perform_cb _hidl_cb);
|
||||
ndk::ScopedAStatus on(uint32_t timeoutMs, const char mode[],
|
||||
const std::unique_ptr<VibrationConfig> &config, const int8_t volOffset);
|
||||
ndk::ScopedAStatus performEffect(Effect effect, EffectStrength strength, int32_t *outTimeMs);
|
||||
|
||||
std::unique_ptr<HwApi> mHwApi;
|
||||
std::unique_ptr<HwCal> mHwCal;
|
||||
uint32_t mCloseLoopThreshold;
|
||||
@@ -201,10 +197,7 @@ class Vibrator : public IVibrator {
|
||||
bool mDynamicConfig;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_3
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_VIBRATOR_V1_3_VIBRATOR_H
|
||||
} // namespace aidl
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
service vendor.vibrator-1-3 /vendor/bin/hw/android.hardware.vibrator@1.3-service.bramble
|
||||
service vendor.vibrator.bramble /vendor/bin/hw/android.hardware.vibrator-service.bramble
|
||||
class hal
|
||||
user system
|
||||
group system
|
||||
@@ -0,0 +1,6 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.vibrator</name>
|
||||
<fqname>IVibrator/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
@@ -1,11 +0,0 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="hidl">
|
||||
<name>android.hardware.vibrator</name>
|
||||
<transport>hwbinder</transport>
|
||||
<version>1.3</version>
|
||||
<interface>
|
||||
<name>IVibrator</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
</manifest>
|
||||
@@ -21,18 +21,12 @@
|
||||
#include "Hardware.h"
|
||||
#include "Vibrator.h"
|
||||
|
||||
using ::android::sp;
|
||||
using ::android::hardware::hidl_enum_range;
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace V1_3 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::base::SetProperty;
|
||||
using ::android::hardware::vibrator::V1_0::EffectStrength;
|
||||
using ::android::hardware::vibrator::V1_0::Status;
|
||||
|
||||
class VibratorBench : public benchmark::Fixture {
|
||||
private:
|
||||
@@ -71,7 +65,7 @@ class VibratorBench : public benchmark::Fixture {
|
||||
|
||||
SetProperty(std::string() + PROPERTY_PREFIX + "config.dynamic", getDynamicConfig(state));
|
||||
|
||||
mVibrator = new Vibrator(HwApi::Create(), std::make_unique<HwCal>());
|
||||
mVibrator = ndk::SharedRefBase::make<Vibrator>(HwApi::Create(), std::make_unique<HwCal>());
|
||||
}
|
||||
|
||||
static void DefaultConfig(benchmark::internal::Benchmark *b) {
|
||||
@@ -95,7 +89,7 @@ class VibratorBench : public benchmark::Fixture {
|
||||
|
||||
protected:
|
||||
TemporaryDir mFilesDir;
|
||||
sp<IVibrator> mVibrator;
|
||||
std::shared_ptr<IVibrator> mVibrator;
|
||||
};
|
||||
|
||||
#define BENCHMARK_WRAPPER(fixt, test, code) \
|
||||
@@ -109,7 +103,7 @@ BENCHMARK_WRAPPER(VibratorBench, on, {
|
||||
uint32_t duration = std::rand() ?: 1;
|
||||
|
||||
for (auto _ : state) {
|
||||
mVibrator->on(duration);
|
||||
mVibrator->on(duration, nullptr);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -119,12 +113,6 @@ BENCHMARK_WRAPPER(VibratorBench, off, {
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench, supportsAmplitudeControl, {
|
||||
for (auto _ : state) {
|
||||
mVibrator->supportsAmplitudeControl();
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench, setAmplitude, {
|
||||
uint8_t amplitude = std::rand() ?: 1;
|
||||
|
||||
@@ -133,12 +121,6 @@ BENCHMARK_WRAPPER(VibratorBench, setAmplitude, {
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench, supportsExternalControl, {
|
||||
for (auto _ : state) {
|
||||
mVibrator->supportsExternalControl();
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench, setExternalControl_enable, {
|
||||
for (auto _ : state) {
|
||||
mVibrator->setExternalControl(true);
|
||||
@@ -151,13 +133,21 @@ BENCHMARK_WRAPPER(VibratorBench, setExternalControl_disable, {
|
||||
}
|
||||
});
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorBench, getCapabilities, {
|
||||
int32_t capabilities;
|
||||
|
||||
for (auto _ : state) {
|
||||
mVibrator->getCapabilities(&capabilities);
|
||||
}
|
||||
});
|
||||
|
||||
class VibratorEffectsBench : public VibratorBench {
|
||||
public:
|
||||
static void DefaultArgs(benchmark::internal::Benchmark *b) {
|
||||
b->ArgNames({"DynamicConfig", "Effect", "Strength"});
|
||||
for (const auto &dynamic : {false, true}) {
|
||||
for (const auto &effect : hidl_enum_range<Effect>()) {
|
||||
for (const auto &strength : hidl_enum_range<EffectStrength>()) {
|
||||
for (const auto &effect : ndk::enum_range<Effect>()) {
|
||||
for (const auto &strength : ndk::enum_range<EffectStrength>()) {
|
||||
b->Args({dynamic, static_cast<long>(effect), static_cast<long>(strength)});
|
||||
}
|
||||
}
|
||||
@@ -174,30 +164,25 @@ class VibratorEffectsBench : public VibratorBench {
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_WRAPPER(VibratorEffectsBench, perform_1_3, {
|
||||
BENCHMARK_WRAPPER(VibratorEffectsBench, perform, {
|
||||
Effect effect = getEffect(state);
|
||||
EffectStrength strength = getStrength(state);
|
||||
bool supported = true;
|
||||
int32_t lengthMs;
|
||||
|
||||
mVibrator->perform_1_3(effect, strength, [&](Status status, uint32_t /*lengthMs*/) {
|
||||
if (status == Status::UNSUPPORTED_OPERATION) {
|
||||
supported = false;
|
||||
}
|
||||
});
|
||||
ndk::ScopedAStatus status = mVibrator->perform(effect, strength, nullptr, &lengthMs);
|
||||
|
||||
if (!supported) {
|
||||
if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto _ : state) {
|
||||
mVibrator->perform_1_3(effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {});
|
||||
mVibrator->perform(effect, strength, nullptr, &lengthMs);
|
||||
}
|
||||
});
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_3
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
||||
@@ -13,47 +13,34 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <android/hardware/vibrator/1.3/IVibrator.h>
|
||||
#include <hidl/HidlSupport.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
#include "Hardware.h"
|
||||
#include "Vibrator.h"
|
||||
|
||||
using android::OK;
|
||||
using android::sp;
|
||||
using android::status_t;
|
||||
using android::UNKNOWN_ERROR;
|
||||
using android::hardware::configureRpcThreadpool;
|
||||
using android::hardware::joinRpcThreadpool;
|
||||
using android::hardware::vibrator::V1_3::implementation::HwApi;
|
||||
using android::hardware::vibrator::V1_3::implementation::HwCal;
|
||||
using android::hardware::vibrator::V1_3::implementation::Vibrator;
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
#include <log/log.h>
|
||||
|
||||
status_t registerVibratorService() {
|
||||
using aidl::android::hardware::vibrator::HwApi;
|
||||
using aidl::android::hardware::vibrator::HwCal;
|
||||
using aidl::android::hardware::vibrator::Vibrator;
|
||||
|
||||
int main() {
|
||||
auto hwapi = HwApi::Create();
|
||||
|
||||
if (!hwapi) {
|
||||
return UNKNOWN_ERROR;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
sp<Vibrator> vibrator = new Vibrator(std::move(hwapi), std::make_unique<HwCal>());
|
||||
|
||||
return vibrator->registerAsService();
|
||||
}
|
||||
|
||||
int main() {
|
||||
// One thread for vibrator APIs and one for sensor callback
|
||||
// WARN: there could be an issue if two vibrator APIs are called simultaneously
|
||||
configureRpcThreadpool(2, true);
|
||||
status_t status = registerVibratorService();
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(1);
|
||||
std::shared_ptr<Vibrator> vib =
|
||||
ndk::SharedRefBase::make<Vibrator>(std::move(hwapi), std::make_unique<HwCal>());
|
||||
|
||||
if (status != OK) {
|
||||
return status;
|
||||
}
|
||||
const std::string instance = std::string() + Vibrator::descriptor + "/default";
|
||||
binder_status_t status = AServiceManager_addService(vib->asBinder().get(), instance.c_str());
|
||||
LOG_ALWAYS_FATAL_IF(status != STATUS_OK);
|
||||
|
||||
joinRpcThreadpool();
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include "Vibrator.h"
|
||||
|
||||
class MockApi : public ::android::hardware::vibrator::V1_3::implementation::Vibrator::HwApi {
|
||||
class MockApi : public ::aidl::android::hardware::vibrator::Vibrator::HwApi {
|
||||
public:
|
||||
MOCK_METHOD0(destructor, void());
|
||||
MOCK_METHOD1(setAutocal, bool(std::string value));
|
||||
@@ -41,7 +41,7 @@ class MockApi : public ::android::hardware::vibrator::V1_3::implementation::Vibr
|
||||
~MockApi() override { destructor(); };
|
||||
};
|
||||
|
||||
class MockCal : public ::android::hardware::vibrator::V1_3::implementation::Vibrator::HwCal {
|
||||
class MockCal : public ::aidl::android::hardware::vibrator::Vibrator::HwCal {
|
||||
public:
|
||||
MOCK_METHOD0(destructor, void());
|
||||
MOCK_METHOD1(getAutocal, bool(std::string &value)); // NOLINT
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
|
||||
#include "Hardware.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace V1_3 {
|
||||
namespace implementation {
|
||||
|
||||
using ::testing::Test;
|
||||
using ::testing::TestParamInfo;
|
||||
@@ -394,8 +393,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
}),
|
||||
SetStringTest::PrintParam);
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_3
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
|
||||
@@ -22,11 +22,10 @@
|
||||
|
||||
#include "Hardware.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace V1_3 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::base::SetProperty;
|
||||
using ::android::base::WaitForProperty;
|
||||
@@ -389,8 +388,7 @@ TEST_F(HwCalTest, trimming) {
|
||||
EXPECT_EQ(lraPeriodExpect, lraPeriodActual);
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_3
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
|
||||
@@ -23,14 +23,10 @@
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace vibrator {
|
||||
namespace V1_3 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::vibrator::V1_0::EffectStrength;
|
||||
using ::android::hardware::vibrator::V1_0::Status;
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::AnyNumber;
|
||||
@@ -181,7 +177,7 @@ class VibratorTestTemplate : public Test, public WithParamInterface<std::tuple<b
|
||||
if (relaxed) {
|
||||
relaxMock(true);
|
||||
}
|
||||
mVibrator = new Vibrator(std::move(mockapi), std::move(mockcal));
|
||||
mVibrator = ndk::SharedRefBase::make<Vibrator>(std::move(mockapi), std::move(mockcal));
|
||||
if (relaxed) {
|
||||
relaxMock(false);
|
||||
}
|
||||
@@ -191,7 +187,7 @@ class VibratorTestTemplate : public Test, public WithParamInterface<std::tuple<b
|
||||
if (relaxed) {
|
||||
relaxMock(true);
|
||||
}
|
||||
mVibrator.clear();
|
||||
mVibrator.reset();
|
||||
}
|
||||
|
||||
void relaxMock(bool relax) {
|
||||
@@ -235,7 +231,7 @@ class VibratorTestTemplate : public Test, public WithParamInterface<std::tuple<b
|
||||
protected:
|
||||
MockApi *mMockApi;
|
||||
MockCal *mMockCal;
|
||||
sp<IVibrator> mVibrator;
|
||||
std::shared_ptr<IVibrator> mVibrator;
|
||||
|
||||
EffectDuration mCloseLoopThreshold;
|
||||
uint32_t mLongFrequencyShift;
|
||||
@@ -310,7 +306,7 @@ TEST_P(BasicTest, on) {
|
||||
|
||||
EXPECT_CALL(*mMockApi, setActivate(true)).After(e).WillOnce(DoDefault());
|
||||
|
||||
EXPECT_EQ(Status::OK, mVibrator->on(duration));
|
||||
EXPECT_EQ(EX_NONE, mVibrator->on(duration, nullptr).getExceptionCode());
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, on_openLoop) {
|
||||
@@ -320,7 +316,7 @@ TEST_P(BasicTest, on_openLoop) {
|
||||
|
||||
EXPECT_CALL(*mMockApi, setCtrlLoop(true)).WillOnce(DoDefault());
|
||||
|
||||
EXPECT_EQ(Status::OK, mVibrator->on(duration));
|
||||
EXPECT_EQ(EX_NONE, mVibrator->on(duration, nullptr).getExceptionCode());
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, on_closeLoop) {
|
||||
@@ -330,45 +326,53 @@ TEST_P(BasicTest, on_closeLoop) {
|
||||
|
||||
EXPECT_CALL(*mMockApi, setCtrlLoop(false)).WillOnce(DoDefault());
|
||||
|
||||
EXPECT_EQ(Status::OK, mVibrator->on(duration));
|
||||
EXPECT_EQ(EX_NONE, mVibrator->on(duration, nullptr).getExceptionCode());
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, off) {
|
||||
EXPECT_CALL(*mMockApi, setActivate(false)).WillOnce(DoDefault());
|
||||
|
||||
EXPECT_EQ(Status::OK, mVibrator->off());
|
||||
EXPECT_EQ(EX_NONE, mVibrator->off().getExceptionCode());
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, supportsAmplitudeControl_supported) {
|
||||
EXPECT_CALL(*mMockApi, hasRtpInput()).WillOnce(Return(true));
|
||||
|
||||
EXPECT_EQ(true, mVibrator->supportsAmplitudeControl());
|
||||
int32_t capabilities;
|
||||
EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
|
||||
EXPECT_GT(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, supportsAmplitudeControl_unsupported) {
|
||||
EXPECT_CALL(*mMockApi, hasRtpInput()).WillOnce(Return(false));
|
||||
|
||||
EXPECT_EQ(false, mVibrator->supportsAmplitudeControl());
|
||||
int32_t capabilities;
|
||||
EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
|
||||
EXPECT_EQ(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, setAmplitude) {
|
||||
EffectAmplitude amplitude = std::rand();
|
||||
EffectAmplitude amplitude = static_cast<float>(std::rand()) / RAND_MAX ?: 1.0f;
|
||||
|
||||
EXPECT_CALL(*mMockApi, setRtpInput(amplitudeToRtpInput(amplitude))).WillOnce(Return(true));
|
||||
|
||||
EXPECT_EQ(Status::OK, mVibrator->setAmplitude(amplitude));
|
||||
EXPECT_EQ(EX_NONE, mVibrator->setAmplitude(amplitude).getExceptionCode());
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, supportsExternalControl_unsupported) {
|
||||
EXPECT_EQ(false, mVibrator->supportsExternalControl());
|
||||
EXPECT_CALL(*mMockApi, hasRtpInput()).WillOnce(Return(false));
|
||||
|
||||
int32_t capabilities;
|
||||
EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
|
||||
EXPECT_EQ(capabilities & IVibrator::CAP_EXTERNAL_CONTROL, 0);
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, setExternalControl_enable) {
|
||||
EXPECT_EQ(Status::UNSUPPORTED_OPERATION, mVibrator->setExternalControl(true));
|
||||
EXPECT_EQ(EX_UNSUPPORTED_OPERATION, mVibrator->setExternalControl(true).getExceptionCode());
|
||||
}
|
||||
|
||||
TEST_P(BasicTest, setExternalControl_disable) {
|
||||
EXPECT_EQ(Status::UNSUPPORTED_OPERATION, mVibrator->setExternalControl(false));
|
||||
EXPECT_EQ(EX_UNSUPPORTED_OPERATION, mVibrator->setExternalControl(false).getExceptionCode());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(VibratorTests, BasicTest,
|
||||
@@ -423,27 +427,25 @@ TEST_P(EffectsTest, perform) {
|
||||
duration = 0;
|
||||
}
|
||||
|
||||
mVibrator->perform_1_3(effect, strength, [&](Status status, uint32_t lengthMs) {
|
||||
if (duration) {
|
||||
EXPECT_EQ(Status::OK, status);
|
||||
EXPECT_LE(duration, lengthMs);
|
||||
} else {
|
||||
EXPECT_EQ(Status::UNSUPPORTED_OPERATION, status);
|
||||
EXPECT_EQ(0, lengthMs);
|
||||
}
|
||||
});
|
||||
int32_t lengthMs;
|
||||
ndk::ScopedAStatus status = mVibrator->perform(effect, strength, nullptr, &lengthMs);
|
||||
if (duration) {
|
||||
EXPECT_EQ(EX_NONE, status.getExceptionCode());
|
||||
EXPECT_LE(duration, lengthMs);
|
||||
} else {
|
||||
EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(VibratorTests, EffectsTest,
|
||||
Combine(ValuesIn({false, true}),
|
||||
Combine(ValuesIn(hidl_enum_range<Effect>().begin(),
|
||||
hidl_enum_range<Effect>().end()),
|
||||
ValuesIn(hidl_enum_range<EffectStrength>().begin(),
|
||||
hidl_enum_range<EffectStrength>().end()))),
|
||||
Combine(ValuesIn(ndk::enum_range<Effect>().begin(),
|
||||
ndk::enum_range<Effect>().end()),
|
||||
ValuesIn(ndk::enum_range<EffectStrength>().begin(),
|
||||
ndk::enum_range<EffectStrength>().end()))),
|
||||
EffectsTest::PrintParam);
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_3
|
||||
} // namespace vibrator
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
#ifndef ANDROID_HARDWARE_VIBRATOR_TEST_TYPES_H
|
||||
#define ANDROID_HARDWARE_VIBRATOR_TEST_TYPES_H
|
||||
|
||||
#include <android/hardware/vibrator/1.3/IVibrator.h>
|
||||
#include <aidl/android/hardware/vibrator/IVibrator.h>
|
||||
|
||||
using EffectAmplitude = uint8_t;
|
||||
using EffectAmplitude = float;
|
||||
using EffectDuration = uint32_t;
|
||||
using EffectSequence = std::tuple<std::string, uint8_t>;
|
||||
using EffectTuple = std::tuple<::android::hardware::vibrator::V1_3::Effect,
|
||||
::android::hardware::vibrator::V1_0::EffectStrength>;
|
||||
using EffectTuple = std::tuple<::aidl::android::hardware::vibrator::Effect,
|
||||
::aidl::android::hardware::vibrator::EffectStrength>;
|
||||
|
||||
#endif // ANDROID_HARDWARE_VIBRATOR_TEST_TYPES_H
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "types.h"
|
||||
|
||||
static inline int32_t amplitudeToRtpInput(EffectAmplitude amplitude) {
|
||||
return std::round((amplitude - 1) / 254.0 * 127);
|
||||
return std::round(amplitude * 127);
|
||||
}
|
||||
|
||||
#endif // ANDROID_HARDWARE_VIBRATOR_TEST_UTILS_H
|
||||
|
||||
Reference in New Issue
Block a user