Merge "Add hwcomposer to the system-background cpuset for hal v2.2" into pi-dev am: f053b3de23
am: db4740805a
Change-Id: Ie87f06f6689921ed1afaaaca168e19f8e5838232
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index dab9f7c..9be9b12 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -1100,11 +1100,10 @@
}
TEST_P(InputStreamTest, getActiveMicrophones) {
- doc::test("Getting active microphones should always succeed");
+ doc::test("Active microphones of a non started stream may not be retrievable");
hidl_vec<MicrophoneInfo> microphones;
- ASSERT_OK(device->getMicrophones(returnIn(res, microphones)));
- ASSERT_OK(res);
- ASSERT_TRUE(microphones.size() > 0);
+ ASSERT_OK(stream->getActiveMicrophones(returnIn(res, microphones)));
+ ASSERT_RESULT(okOrNotSupported, res);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
index 43e5d6e..a9f59fb 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
@@ -106,8 +106,8 @@
return rc;
}
-IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) {
- return new DevicesFactory();
+IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name) {
+ return strcmp(name, "default") == 0 ? new DevicesFactory() : nullptr;
}
} // namespace implementation
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
index 1882a2c..f27c739 100644
--- a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
@@ -183,8 +183,8 @@
return Void();
}
-IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* /* name */) {
- return new EffectsFactory();
+IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* name) {
+ return strcmp(name, "default") == 0 ? new EffectsFactory() : nullptr;
}
} // namespace implementation
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 22ab079..65e9133 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -64,6 +64,7 @@
"impl/vhal_v2_0/SocketComm.cpp",
"impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
"impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
+ "impl/vhal_v2_0/GeneratorHub.cpp",
],
local_include_dirs: ["common/include/vhal_v2_0"],
export_include_dirs: ["impl"],
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index eb9d660..50f3622 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -70,33 +70,39 @@
enum class FakeDataCommand : int32_t {
/**
* Starts linear fake data generation. Caller must provide additional data:
- * int32Values[1] - VehicleProperty to which command applies
+ * int32Values[1] - vehicle property to which command applies
* int64Values[0] - periodic interval in nanoseconds
* floatValues[0] - initial value
* floatValues[1] - dispersion defines the min/max value relative to initial value, where
* max = initial_value + dispersion, min = initial_value - dispersion.
* Dispersion should be non-negative, otherwise the behavior is undefined.
* floatValues[2] - increment, with every timer tick the value will be incremented by this
- * amount. When reaching to max value, the current value will be set to min.
- * It should be non-negative, otherwise the behavior is undefined.
+ * amount. When reaching to max value, the current value will be set to
+ * min. It should be non-negative, otherwise the behavior is undefined.
*/
StartLinear = 0,
- /** Stops generating of fake data that was triggered by Start commands.
- * int32Values[1] - VehicleProperty to which command applies. VHAL will stop the
+ /** Stops linear fake data generation that was triggered by StartLinear commands.
+ * int32Values[1] - vehicle property to which command applies. VHAL will stop the
* corresponding linear generation for that property.
*/
StopLinear = 1,
/**
- * Starts JSON-based fake data generation. Caller must provide a string value specifying
- * the path to fake value JSON file:
+ * Starts JSON-based fake data generation. It iterates through JSON-encoded VHAL events from a
+ * file and inject them to VHAL. The iteration can be repeated multiple times or infinitely.
+ * Caller must provide additional data:
+ * int32Values[1] - number of iterations. If it is not provided or -1. The iteration will be
+ * repeated infinite times.
* stringValue - path to the fake values JSON file
*/
StartJson = 2,
/**
- * Stops JSON-based fake data generation. No additional arguments needed.
+ * Stops JSON-based fake data generation. As multiple JSON-based generation can happen at the
+ * same time. Caller must provide the path of fake value JSON file to stop the corresponding
+ * generation:
+ * stringValue - path to the fake values JSON file
*/
StopJson = 3,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 07695bf..0e5897a 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -92,10 +92,8 @@
mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
mRecurrentTimer(
std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)),
- mLinearFakeValueGenerator(std::make_unique<LinearFakeValueGenerator>(
- std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))),
- mJsonFakeValueGenerator(std::make_unique<JsonFakeValueGenerator>(
- std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))) {
+ mGeneratorHub(
+ std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1)) {
initStaticConfig();
for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
mPropStore->registerProperty(kVehicleProperties[i].config);
@@ -343,19 +341,54 @@
switch (command) {
case FakeDataCommand::StartLinear: {
ALOGI("%s, FakeDataCommand::StartLinear", __func__);
- return mLinearFakeValueGenerator->start(request);
+ if (v.int32Values.size() < 2) {
+ ALOGE("%s: expected property ID in int32Values", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ if (!v.int64Values.size()) {
+ ALOGE("%s: interval is not provided in int64Values", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ if (v.floatValues.size() < 3) {
+ ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__,
+ v.floatValues.size());
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ mGeneratorHub.registerGenerator(cookie,
+ std::make_unique<LinearFakeValueGenerator>(request));
+ break;
}
case FakeDataCommand::StartJson: {
ALOGI("%s, FakeDataCommand::StartJson", __func__);
- return mJsonFakeValueGenerator->start(request);
+ if (v.stringValue.empty()) {
+ ALOGE("%s: path to JSON file is missing", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ mGeneratorHub.registerGenerator(cookie,
+ std::make_unique<JsonFakeValueGenerator>(request));
+ break;
}
case FakeDataCommand::StopLinear: {
ALOGI("%s, FakeDataCommand::StopLinear", __func__);
- return mLinearFakeValueGenerator->stop(request);
+ if (v.int32Values.size() < 2) {
+ ALOGE("%s: expected property ID in int32Values", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ mGeneratorHub.unregisterGenerator(cookie);
+ break;
}
case FakeDataCommand::StopJson: {
ALOGI("%s, FakeDataCommand::StopJson", __func__);
- return mJsonFakeValueGenerator->stop(request);
+ if (v.stringValue.empty()) {
+ ALOGE("%s: path to JSON file is missing", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ mGeneratorHub.unregisterGenerator(cookie);
+ break;
}
case FakeDataCommand::KeyPress: {
ALOGI("%s, FakeDataCommand::KeyPress", __func__);
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index c188aef..ec59690 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -30,8 +30,7 @@
#include "vhal_v2_0/VehiclePropertyStore.h"
#include "DefaultConfig.h"
-#include "FakeValueGenerator.h"
-
+#include "GeneratorHub.h"
#include "VehicleEmulator.h"
namespace android {
@@ -85,8 +84,7 @@
VehiclePropertyStore* mPropStore;
std::unordered_set<int32_t> mHvacPowerProps;
RecurrentTimer mRecurrentTimer;
- std::unique_ptr<FakeValueGenerator> mLinearFakeValueGenerator;
- std::unique_ptr<FakeValueGenerator> mJsonFakeValueGenerator;
+ GeneratorHub mGeneratorHub;
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
index 1eeb88d..d6ad77d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
@@ -27,28 +27,22 @@
namespace impl {
-using OnHalEvent = std::function<void(const VehiclePropValue& event)>;
-using MuxGuard = std::lock_guard<std::mutex>;
-
class FakeValueGenerator {
public:
virtual ~FakeValueGenerator() = default;
- /**
- * Starts generating VHAL events
- *
- * @param request in VehiclePropValue with required information to start fake data generation
- * @return StatusCode of the start request
- */
- virtual StatusCode start(const VehiclePropValue& request) = 0;
- /**
- * Stops generating VHAL events
- * @param request in VehiclePropValue with required information to stop fake data generation
- * @return StatusCode of the stop request
- */
- virtual StatusCode stop(const VehiclePropValue& request) = 0;
+
+ virtual VehiclePropValue nextEvent() = 0;
+
+ virtual bool hasNext() = 0;
};
-} // impl
+using Clock = std::chrono::steady_clock;
+using Nanos = std::chrono::nanoseconds;
+using TimePoint = std::chrono::time_point<Clock, Nanos>;
+
+using FakeValueGeneratorPtr = std::unique_ptr<FakeValueGenerator>;
+
+} // namespace impl
} // namespace V2_0
} // namespace vehicle
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
new file mode 100644
index 0000000..548285a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "GeneratorHub"
+
+#include <log/log.h>
+
+#include "GeneratorHub.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+GeneratorHub::GeneratorHub(const OnHalEvent& onHalEvent)
+ : mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
+
+void GeneratorHub::registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator) {
+ {
+ std::lock_guard<std::mutex> g(mLock);
+ // Register only if the generator can produce event
+ if (generator->hasNext()) {
+ // Push the next event if it is a new generator
+ if (mGenerators.find(cookie) == mGenerators.end()) {
+ ALOGI("%s: Registering new generator, cookie: %d", __func__, cookie);
+ mEventQueue.push({cookie, generator->nextEvent()});
+ }
+ mGenerators[cookie] = std::move(generator);
+ ALOGI("%s: Registered generator, cookie: %d", __func__, cookie);
+ }
+ }
+ mCond.notify_one();
+}
+
+void GeneratorHub::unregisterGenerator(int32_t cookie) {
+ {
+ std::lock_guard<std::mutex> g(mLock);
+ mGenerators.erase(cookie);
+ }
+ mCond.notify_one();
+ ALOGI("%s: Unregistered generator, cookie: %d", __func__, cookie);
+}
+
+void GeneratorHub::run() {
+ while (true) {
+ std::unique_lock<std::mutex> g(mLock);
+ // Pop events whose generator does not exist (may be already unregistered)
+ while (!mEventQueue.empty()
+ && mGenerators.find(mEventQueue.top().cookie) == mGenerators.end()) {
+ mEventQueue.pop();
+ }
+ // Wait until event queue is not empty
+ mCond.wait(g, [this] { return !mEventQueue.empty(); });
+
+ const VhalEvent& curEvent = mEventQueue.top();
+
+ TimePoint eventTime(Nanos(curEvent.val.timestamp));
+ // Wait until the soonest event happen
+ if (mCond.wait_until(g, eventTime) != std::cv_status::timeout) {
+ // It is possible that a new generator is registered and produced a sooner event, or current
+ // generator is unregistered, in this case the thread will re-evaluate the soonest event
+ ALOGI("Something happened while waiting");
+ continue;
+ }
+ // Now it's time to handle current event.
+ mOnHalEvent(curEvent.val);
+ // Update queue by popping current event and producing next event from the same generator
+ int32_t cookie = curEvent.cookie;
+ mEventQueue.pop();
+ if (hasNext(cookie)) {
+ mEventQueue.push({cookie, mGenerators[cookie]->nextEvent()});
+ } else {
+ ALOGI("%s: Generator ended, unregister it, cookie: %d", __func__, cookie);
+ mGenerators.erase(cookie);
+ }
+ }
+}
+
+bool GeneratorHub::hasNext(int32_t cookie) {
+ return mGenerators.find(cookie) != mGenerators.end() && mGenerators[cookie]->hasNext();
+}
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
new file mode 100644
index 0000000..dcf6a4f
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 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_automotive_vehicle_V2_0_impl_GeneratorHub_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_GeneratorHub_H_
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <iostream>
+#include <queue>
+#include <thread>
+#include <unordered_map>
+
+#include "FakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+/**
+ * This is the scheduler for all VHAL event generators. It manages all generators and uses priority
+ * queue to maintain generated events ordered by timestamp. The scheduler uses a single thread to
+ * keep querying and updating the event queue to make sure events from all generators are produced
+ * in order.
+ */
+class GeneratorHub {
+private:
+ struct VhalEvent {
+ int32_t cookie; // Cookie is used to find the associated generator.
+ VehiclePropValue val;
+ };
+ // Comparator used by priority queue to keep track of soonest event.
+ struct GreaterByTime {
+ bool operator()(const VhalEvent& lhs, const VhalEvent& rhs) const {
+ return lhs.val.timestamp > rhs.val.timestamp;
+ }
+ };
+
+ using OnHalEvent = std::function<void(const VehiclePropValue& event)>;
+
+public:
+ GeneratorHub(const OnHalEvent& onHalEvent);
+ ~GeneratorHub() = default;
+
+ /**
+ * Register a new generator. The generator will be discarded if it could not produce next event.
+ * The existing generator will be overridden if it has the same cookie.
+ */
+ void registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator);
+
+ void unregisterGenerator(int32_t cookie);
+
+private:
+ /**
+ * Main loop of the single thread to producing event and updating event queue.
+ */
+ void run();
+
+ bool hasNext(int32_t cookie);
+
+private:
+ std::priority_queue<VhalEvent, std::vector<VhalEvent>, GreaterByTime> mEventQueue;
+ std::unordered_map<int32_t, FakeValueGeneratorPtr> mGenerators;
+ OnHalEvent mOnHalEvent;
+
+ mutable std::mutex mLock;
+ std::condition_variable mCond;
+ std::thread mThread;
+};
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_GeneratorHub_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
index 88b8f86..c293c0a 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -31,57 +31,48 @@
namespace impl {
-JsonFakeValueGenerator::JsonFakeValueGenerator(const OnHalEvent& onHalEvent)
- : mOnHalEvent(onHalEvent), mThread(&JsonFakeValueGenerator::loop, this) {}
-
-JsonFakeValueGenerator::~JsonFakeValueGenerator() {
- mStopRequested = true;
- {
- MuxGuard g(mLock);
- mGenCfg.index = 0;
- mGenCfg.events.clear();
- }
- mCond.notify_one();
- if (mThread.joinable()) {
- mThread.join();
- }
-}
-
-StatusCode JsonFakeValueGenerator::start(const VehiclePropValue& request) {
+JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
const auto& v = request.value;
- if (v.stringValue.empty()) {
- ALOGE("%s: path to JSON file is missing", __func__);
- return StatusCode::INVALID_ARG;
- }
const char* file = v.stringValue.c_str();
std::ifstream ifs(file);
if (!ifs) {
ALOGE("%s: couldn't open %s for parsing.", __func__, file);
- return StatusCode::INTERNAL_ERROR;
}
- std::vector<VehiclePropValue> fakeVhalEvents = parseFakeValueJson(ifs);
-
- {
- MuxGuard g(mLock);
- mGenCfg = {0, fakeVhalEvents};
- }
- mCond.notify_one();
- return StatusCode::OK;
+ mGenCfg = {
+ .index = 0,
+ .events = parseFakeValueJson(ifs),
+ };
+ // Iterate infinitely if repetition number is not provided
+ mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
}
-StatusCode JsonFakeValueGenerator::stop(const VehiclePropValue& request) {
- const auto& v = request.value;
- if (!v.stringValue.empty()) {
- ALOGI("%s: %s", __func__, v.stringValue.c_str());
+VehiclePropValue JsonFakeValueGenerator::nextEvent() {
+ VehiclePropValue generatedValue;
+ if (!hasNext()) {
+ return generatedValue;
}
+ TimePoint eventTime = Clock::now();
+ if (mGenCfg.index != 0) {
+ // All events (start from 2nd one) are supposed to happen in the future with a delay
+ // equals to the duration between previous and current event.
+ eventTime += Nanos(mGenCfg.events[mGenCfg.index].timestamp -
+ mGenCfg.events[mGenCfg.index - 1].timestamp);
+ }
+ generatedValue = mGenCfg.events[mGenCfg.index];
+ generatedValue.timestamp = eventTime.time_since_epoch().count();
- {
- MuxGuard g(mLock);
+ mGenCfg.index++;
+ if (mGenCfg.index == mGenCfg.events.size()) {
mGenCfg.index = 0;
- mGenCfg.events.clear();
+ if (mNumOfIterations > 0) {
+ mNumOfIterations--;
+ }
}
- mCond.notify_one();
- return StatusCode::OK;
+ return generatedValue;
+}
+
+bool JsonFakeValueGenerator::hasNext() {
+ return mNumOfIterations != 0 && mGenCfg.events.size() > 0;
}
std::vector<VehiclePropValue> JsonFakeValueGenerator::parseFakeValueJson(std::istream& is) {
@@ -141,30 +132,6 @@
return fakeVhalEvents;
}
-void JsonFakeValueGenerator::loop() {
- static constexpr auto kInvalidTime = TimePoint(Nanos::max());
-
- while (!mStopRequested) {
- auto nextEventTime = kInvalidTime;
- {
- MuxGuard g(mLock);
- if (mGenCfg.index < mGenCfg.events.size()) {
- mOnHalEvent(mGenCfg.events[mGenCfg.index]);
- }
- if (!mGenCfg.events.empty() && mGenCfg.index < mGenCfg.events.size() - 1) {
- Nanos intervalNano =
- static_cast<Nanos>(mGenCfg.events[mGenCfg.index + 1].timestamp -
- mGenCfg.events[mGenCfg.index].timestamp);
- nextEventTime = Clock::now() + intervalNano;
- }
- mGenCfg.index++;
- }
-
- std::unique_lock<std::mutex> g(mLock);
- mCond.wait_until(g, nextEventTime);
- }
-}
-
} // namespace impl
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
index 51da4c5..43c8b9d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -17,11 +17,8 @@
#ifndef android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_
#define android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_
-#include <atomic>
#include <chrono>
-#include <condition_variable>
#include <iostream>
-#include <thread>
#include <json/json.h>
@@ -37,32 +34,25 @@
class JsonFakeValueGenerator : public FakeValueGenerator {
private:
- using Nanos = std::chrono::nanoseconds;
- using Clock = std::chrono::steady_clock;
- using TimePoint = std::chrono::time_point<Clock, Nanos>;
-
struct GeneratorCfg {
size_t index;
std::vector<VehiclePropValue> events;
};
public:
- JsonFakeValueGenerator(const OnHalEvent& onHalEvent);
- ~JsonFakeValueGenerator();
- StatusCode start(const VehiclePropValue& request) override;
- StatusCode stop(const VehiclePropValue& request) override;
+ JsonFakeValueGenerator(const VehiclePropValue& request);
+ ~JsonFakeValueGenerator() = default;
+
+ VehiclePropValue nextEvent();
+
+ bool hasNext();
private:
std::vector<VehiclePropValue> parseFakeValueJson(std::istream& is);
- void loop();
private:
- OnHalEvent mOnHalEvent;
- std::thread mThread;
- mutable std::mutex mLock;
- std::condition_variable mCond;
GeneratorCfg mGenCfg;
- std::atomic_bool mStopRequested{false};
+ int32_t mNumOfIterations;
};
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
index 8cb9322..7bdc97c 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
@@ -29,101 +29,48 @@
namespace impl {
-LinearFakeValueGenerator::LinearFakeValueGenerator(const OnHalEvent& onHalEvent)
- : mOnHalEvent(onHalEvent),
- mRecurrentTimer(std::bind(&LinearFakeValueGenerator::onTimer, this, std::placeholders::_1)) {}
-
-StatusCode LinearFakeValueGenerator::start(const VehiclePropValue& request) {
+LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) {
const auto& v = request.value;
- if (v.int32Values.size() < 2) {
- ALOGE("%s: expected property ID in int32Values", __func__);
- return StatusCode::INVALID_ARG;
- }
- int32_t propId = v.int32Values[1];
-
- if (!v.int64Values.size()) {
- ALOGE("%s: interval is not provided in int64Values", __func__);
- return StatusCode::INVALID_ARG;
- }
- auto interval = std::chrono::nanoseconds(v.int64Values[0]);
-
- if (v.floatValues.size() < 3) {
- ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__,
- v.floatValues.size());
- return StatusCode::INVALID_ARG;
- }
- float initialValue = v.floatValues[0];
- float dispersion = v.floatValues[1];
- float increment = v.floatValues[2];
-
- MuxGuard g(mLock);
- removeLocked(propId);
- mGenCfg.insert({propId, GeneratorCfg{
- .initialValue = initialValue,
- .currentValue = initialValue,
- .dispersion = dispersion,
- .increment = increment,}});
-
- mRecurrentTimer.registerRecurrentEvent(interval, propId);
- return StatusCode::OK;
+ mGenCfg = GeneratorCfg{
+ .propId = v.int32Values[1],
+ .initialValue = v.floatValues[0],
+ .currentValue = v.floatValues[0],
+ .dispersion = v.floatValues[1],
+ .increment = v.floatValues[2],
+ .interval = Nanos(v.int64Values[0]),
+ };
}
-StatusCode LinearFakeValueGenerator::stop(const VehiclePropValue& request) {
- const auto& v = request.value;
- if (v.int32Values.size() < 2) {
- ALOGE("%s: expected property ID in int32Values", __func__);
- return StatusCode::INVALID_ARG;
+VehiclePropValue LinearFakeValueGenerator::nextEvent() {
+ mGenCfg.currentValue += mGenCfg.increment;
+ if (mGenCfg.currentValue > mGenCfg.initialValue + mGenCfg.dispersion) {
+ mGenCfg.currentValue = mGenCfg.initialValue - mGenCfg.dispersion;
}
- int32_t propId = v.int32Values[1];
-
- MuxGuard g(mLock);
- if (propId == 0) {
- // Remove all.
- for (auto&& it : mGenCfg) {
- removeLocked(it.first);
- }
- } else {
- removeLocked(propId);
+ VehiclePropValue event = {.prop = mGenCfg.propId};
+ auto& value = event.value;
+ switch (getPropType(event.prop)) {
+ case VehiclePropertyType::INT32:
+ value.int32Values.resize(1);
+ value.int32Values[0] = static_cast<int32_t>(mGenCfg.currentValue);
+ break;
+ case VehiclePropertyType::INT64:
+ value.int64Values.resize(1);
+ value.int64Values[0] = static_cast<int64_t>(mGenCfg.currentValue);
+ break;
+ case VehiclePropertyType::FLOAT:
+ value.floatValues.resize(1);
+ value.floatValues[0] = mGenCfg.currentValue;
+ break;
+ default:
+ ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop);
}
- return StatusCode::OK;
+ TimePoint eventTime = Clock::now() + mGenCfg.interval;
+ event.timestamp = eventTime.time_since_epoch().count();
+ return event;
}
-void LinearFakeValueGenerator::removeLocked(int propId) {
- if (mGenCfg.erase(propId)) {
- mRecurrentTimer.unregisterRecurrentEvent(propId);
- }
-}
-
-void LinearFakeValueGenerator::onTimer(const std::vector<int32_t>& properties) {
- MuxGuard g(mLock);
-
- for (int32_t propId : properties) {
- auto& cfg = mGenCfg[propId];
- cfg.currentValue += cfg.increment;
- if (cfg.currentValue > cfg.initialValue + cfg.dispersion) {
- cfg.currentValue = cfg.initialValue - cfg.dispersion;
- }
- VehiclePropValue event = {.prop = propId};
- auto& value = event.value;
- switch (getPropType(event.prop)) {
- case VehiclePropertyType::INT32:
- value.int32Values.resize(1);
- value.int32Values[0] = static_cast<int32_t>(cfg.currentValue);
- break;
- case VehiclePropertyType::INT64:
- value.int64Values.resize(1);
- value.int64Values[0] = static_cast<int64_t>(cfg.currentValue);
- break;
- case VehiclePropertyType::FLOAT:
- value.floatValues.resize(1);
- value.floatValues[0] = cfg.currentValue;
- break;
- default:
- ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop);
- continue;
- }
- mOnHalEvent(event);
- }
+bool LinearFakeValueGenerator::hasNext() {
+ return true;
}
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
index fe6d097..d3b666d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
@@ -17,8 +17,6 @@
#ifndef android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_
#define android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_
-#include <vhal_v2_0/RecurrentTimer.h>
-
#include "FakeValueGenerator.h"
namespace android {
@@ -36,27 +34,24 @@
// to the client.
struct GeneratorCfg {
- float initialValue; //
+ int32_t propId;
+ float initialValue;
float currentValue; // Should be in range (initialValue +/- dispersion).
float dispersion; // Defines minimum and maximum value based on initial value.
float increment; // Value that we will be added to currentValue with each timer tick.
+ Nanos interval;
};
public:
- LinearFakeValueGenerator(const OnHalEvent& onHalEvent);
+ LinearFakeValueGenerator(const VehiclePropValue& request);
~LinearFakeValueGenerator() = default;
- StatusCode start(const VehiclePropValue& request) override;
- StatusCode stop(const VehiclePropValue& request) override;
+
+ VehiclePropValue nextEvent();
+
+ bool hasNext();
private:
- void removeLocked(int propId);
- void onTimer(const std::vector<int32_t>& properties);
-
-private:
- mutable std::mutex mLock;
- OnHalEvent mOnHalEvent;
- RecurrentTimer mRecurrentTimer;
- std::unordered_map<int32_t, GeneratorCfg> mGenCfg;
+ GeneratorCfg mGenCfg;
};
} // namespace impl
diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp
new file mode 100644
index 0000000..61bf247
--- /dev/null
+++ b/biometrics/face/1.0/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.biometrics.face@1.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IBiometricsFace.hal",
+ "IBiometricsFaceClientCallback.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "FaceAcquiredInfo",
+ "FaceError",
+ "OptionalUint64",
+ "Status",
+ "UserHandle",
+ ],
+ gen_java: true,
+}
+
diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal
new file mode 100644
index 0000000..fbdb210
--- /dev/null
+++ b/biometrics/face/1.0/IBiometricsFace.hal
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.face@1.0;
+
+import IBiometricsFaceClientCallback;
+
+// TODO(b/78538290): Update comments with state machine transitions when ready.
+// TODO(b/78537981): Update comments with callback interaction contract.
+// TODO(b/79496983): Update comments with status returns fully enumerated.
+/**
+ * The HAL interface for biometric face authentication.
+ */
+interface IBiometricsFace {
+
+ /**
+ * Sets the current client callback.
+ *
+ * Registers a user function that must receive notifications from the HAL.
+ * There is usually only one client (FaceService). This call must block
+ * if the HAL state machine is in busy state until the HAL leaves the
+ * busy state.
+ *
+ * All callback methods pass a deviceId to differentiate callback
+ * invocations in the case where multiple sensors exist.
+ *
+ * @param clientCallback The client defined callback to register.
+ * @return result, with its "value" parameter representing a "deviceId",
+ * which must be unique for a given sensor.
+ */
+ @callflow(next={"setActiveUser"})
+ @entry
+ setCallback(IBiometricsFaceClientCallback clientCallback)
+ generates (OptionalUint64 result);
+
+ /**
+ * Sets the active user, which all subsequent HAL operations are applied to.
+ *
+ * HAL service implementors must ensure that operations are restricted to
+ * the given user. Clients must not call any part of this interface, except
+ * for setCallback(), without first having set an active user. The
+ * implementation is responsible for cancelling the current operation and
+ * returning to the idle state. Calling this method with the same userId
+ * should have no effect on the state machine.
+ *
+ * @param userId A non-negative user identifier that must be unique and
+ * persistent for a given user.
+ * @param storePath filesystem path to the template storage directory.
+ */
+ @callflow(next={"authenticate", "preEnroll", "enumerate", "remove"})
+ setActiveUser(int32_t userId, string storePath) generates (Status status);
+
+ /**
+ * Begins a pre-enrollment request.
+ *
+ * Generates a unique and cryptographically secure random token used to
+ * indicate the start of an enrollment transaction. preEnroll() and
+ * postEnroll() specify a pin/pattern/password cleared time window where
+ * enrollment is allowed.
+ *
+ * preEnroll() generates a challenge which must then be wrapped by the
+ * gatekeeper after verifying a successful strong authentication attempt,
+ * which generates a Hardware Authentication Token. The challenge prevents
+ * spoofing and replay attacks and ensures that we only update a user’s face
+ * template if the operation was preceded by some kind of strong credential
+ * confirmation (e.g. device password).
+ *
+ * @return result, with its "value" parameter representing a "challenge": a
+ * unique and cryptographically secure random token.
+ */
+ @callflow(next={"enroll", "postEnroll"})
+ preEnroll() generates (OptionalUint64 result);
+
+ /**
+ * Enrolls a user's face.
+ *
+ * Note that this interface permits implementations where multiple faces can
+ * be enrolled for a single user. However, allowing multiple faces to be
+ * enrolled can be a severe security vulnerability and hence, most
+ * implementations must ensure that only a single face be enrolled at a
+ * given time. Multi-enrollment must only be used where there is a clear
+ * necessity for a shared use case, e.g. TVs or cars.
+ *
+ * Note that the Hardware Authentication Token must still be valid after
+ * this call, and must be explicitly invalidated by a call to postEnroll().
+ * This allows clients to immediately reattempt enrollment (for example, if
+ * a user wasn’t satisfied with their enrollment) without having to go
+ * through another strong authentication flow.
+ *
+ * This method triggers the IBiometricsFaceClientCallback#onEnrollResult()
+ * method.
+ *
+ * @param hat A valid Hardware Authentication Token, generated as a result
+ * of a preEnroll() challenge being wrapped by the gatekeeper after a
+ * sucessful strong authentication request.
+ * @param timeoutSec A timeout in seconds, after which this enrollment
+ * attempt is cancelled. Note that the client still needs to
+ * call postEnroll() to terminate the enrollment session.
+ * @return status The status of this method call.
+ */
+ @callflow(next={"cancel", "enroll", "postEnroll", "remove"})
+ enroll(vec<uint8_t> hat, uint32_t timeoutSec) generates (Status status);
+
+ /**
+ * Finishes the enrollment session and invalidates the challenge generated
+ * by preEnroll().
+ *
+ * Clients must call this method once enrollment is complete, and the user's
+ * face template no longer needs to be updated.
+ *
+ * @return status The status of this method call.
+ */
+ @callflow(next={"authenticate", "setActiveUser", "enumerate", "remove"})
+ postEnroll() generates (Status status);
+
+ /**
+ * Returns an identifier associated with the current face set.
+ *
+ * The authenticator ID must change whenever a new face is enrolled. The
+ * authenticator ID must not be changed when a face is deleted. The
+ * authenticator ID must be an entropy-encoded random number which all
+ * current templates are tied to. The authenticator ID must be immutable
+ * outside of an active enrollment window to prevent replay attacks.
+ *
+ * @return result, with its value parameter representing an
+ * "authenticatorId": an identifier associated to the user's current
+ * face enrollment.
+ */
+ @callflow(next={"authenticate"})
+ getAuthenticatorId() generates (OptionalUint64 result);
+
+ /**
+ * Cancels a pending enrollment or authentication request.
+ *
+ * @return status The status of this method call.
+ */
+ @callflow(next={"authenticate", "enroll", "enumerate", "remove",
+ "setActiveUser"})
+ cancel() generates (Status status);
+
+ /**
+ * Enumerates all face templates associated with the active user.
+ *
+ * The onEnumerate() callback method is invoked once for each face template
+ * found.
+ *
+ * @return status The status of this method call.
+ */
+ @callflow(next={"remove", "enroll", "authenticate", "setActiveUser"})
+ enumerate() generates (Status status);
+
+ /**
+ * Removes a face template or all face templates associated with the active
+ * user.
+ *
+ * This method triggers the IBiometricsFaceClientCallback#onRemoved() method.
+ *
+ * @param faceId The id correpsonding to the face to be removed; or 0 if all
+ * faces are to be removed.
+ * @return status The status of this method call.
+ */
+ @callflow(next={"enumerate", "authenticate", "cancel", "getAuthenticatorId",
+ "setActiveUser"})
+ remove(uint32_t faceId) generates (Status status);
+
+ /**
+ * Authenticates the active user.
+ *
+ * An optional operationId can be specified as a token from the transaction
+ * being authorized.
+ *
+ * @param operationId A non-zero operation id associated with a crypto
+ * object instance; or 0 if not being used.
+ * @return status The status of this method call.
+ */
+ @callflow(next={"cancel", "preEnroll", "remove"})
+ authenticate(uint64_t operationId) generates (Status status);
+};
diff --git a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal
new file mode 100644
index 0000000..93848c5
--- /dev/null
+++ b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.face@1.0;
+
+/**
+ * This callback interface is used by clients to recieve updates from the face
+ * HAL.
+ */
+interface IBiometricsFaceClientCallback {
+
+ /**
+ * A callback invoked when one enrollment step has been completed.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that processed this enrollment step.
+ * @param faceId The id of the face template being enrolled.
+ * @param userId The active user id for the template being enrolled.
+ * @param remaining The number of remaining steps before enrolllment is
+ * complete or 0 if enrollment has completed successfully.
+ */
+ oneway onEnrollResult(uint64_t deviceId, uint32_t faceId, int32_t userId,
+ uint32_t remaining);
+
+ /**
+ * A callback invoked when a face has been successfully authenticated.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that processed this autentication attempt.
+ * @param faceId The id of the face template that passed the authentication
+ * challenge.
+ * @param userId The active user id for the authenticated face.
+ * @param token The hardware authentication token associated with this
+ * authenticate operation.
+ */
+ oneway onAuthenticated(uint64_t deviceId, uint32_t faceId, int32_t userId,
+ vec<uint8_t> token);
+
+ /**
+ * A callback invoked when a face is acquired.
+ *
+ * If a non-critical, recoverable error occurs during an enrollment or
+ * authentication attempt, the HAL implementation must invoke this callback
+ * to allow clients to inform the user that some actionable change must be
+ * made.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that acquired a face.
+ * @param userId The id of the active user associated with the attempted
+ * face acquisition.
+ * @param acquiredInfo A message about the quality of the acquired image.
+ * @param vendorCode An optional vendor-specific message. This is only valid
+ * when acquiredInfo == FaceAcquiredInfo.VENDOR. This message is opaque
+ * to the framework, and vendors must provide code to handle it. For
+ * example this can be used to guide enrollment in Settings or provide
+ * a message during authentication that is vendor-specific. The vendor
+ * is expected to provide help strings to cover all known values.
+ */
+ oneway onAcquired(uint64_t deviceId, int32_t userId,
+ FaceAcquiredInfo acquiredInfo, int32_t vendorCode);
+
+ /**
+ * A callback invoked when an error has occured.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service where this error occured.
+ * @param userId The id of the active user when the error occured, or
+ * UserHandle::NONE if an active user had not been set yet.
+ * @param error A message about the error that occurred.
+ * @param vendorCode An optional, vendor-speicifc error message. Only valid
+ * when error == FaceError.VENDOR. This message is opaque to the
+ * framework, and vendors must provide code to handle it. For example,
+ * this scan be used to show the user an error message specific to the
+ * device. The vendor is expected to provide error strings to cover
+ * all known values.
+ */
+ oneway onError(uint64_t deviceId, int32_t userId, FaceError error,
+ int32_t vendorCode);
+
+ /**
+ * A callback invoked when a face template has been removed.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that processed this removal.
+ * @param faceId The id of the face template that was removed.
+ * @param userId The active user id for the removed face template.
+ * @param remaining The number of face templates remaining after this
+ * removal, or 0 if there are no more.
+ */
+ oneway onRemoved(uint64_t deviceId, uint32_t faceId, int32_t userId,
+ uint32_t remaining);
+
+ /**
+ * A callback invoked to enumerate all current face templates.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that processed this enumeration.
+ * @param faceIds A list of ids of all currently enrolled face templates.
+ * @param userId The active user id for the enumerated face template.
+ */
+ oneway onEnumerate(uint64_t deviceId, vec<uint32_t> faceIds,
+ int32_t userId);
+};
diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal
new file mode 100644
index 0000000..08af919
--- /dev/null
+++ b/biometrics/face/1.0/types.hal
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.face@1.0;
+
+/*
+ * In the event setActiveUser is not called, all error messages will return
+ * this userId.
+ */
+enum UserHandle : int32_t {
+ NONE = -1
+};
+
+/**
+ * Status codes returned directly by the HIDL method calls upon critical errors
+ * where the callback cannot be invoked. Most errors should sent through the
+ * onError callback using one of the FaceErrors below.
+ */
+enum Status : uint32_t {
+ /**
+ * The method was invoked successfully.
+ */
+ OK = 0,
+
+ /**
+ * One of the arguments to the method call is invalid.
+ */
+ ILLEGAL_ARGUMENT = 1,
+
+ /**
+ * This face HAL does not support this operation.
+ */
+ OPERATION_NOT_SUPPORTED = 2,
+
+ /**
+ * The HAL has encountered an internal error and cannot complete the request.
+ */
+ INTERNAL_ERROR = 3
+};
+
+/**
+ * Face errors represent events that can't be immediately recovered by user
+ * intervention. These are returned in the onError callback.
+ *
+ * Upon receiving a face error, clients must terminate the current operation and
+ * notify the user where possible.
+ */
+enum FaceError : int32_t {
+
+ /**
+ * A hardware error has occured that cannot be resolved. Try again later.
+ */
+ HW_UNAVAILABLE = 1,
+
+ /**
+ * The current enroll or authenticate operation could not be completed;
+ * the sensor was unable to process the current image.
+ */
+ UNABLE_TO_PROCESS = 2,
+
+ /**
+ * The current operation took too long to complete. This is intended to
+ * prevent programs from blocking the face HAL indefinitely. The timeout is
+ * framework and sensor-specific, but is generally on the order of 30
+ * seconds.
+ */
+ TIMEOUT = 3,
+
+ /**
+ * The current operation could not be completed because there is not enough
+ * storage space remaining to do so.
+ */
+ NO_SPACE = 4,
+
+ /**
+ * The current operation has been cancelled. This may happen if a new
+ * request (authenticate, remove) is initiated while an on-going operation
+ * is in progress, or if cancel() was called.
+ */
+ CANCELED = 5,
+
+ /**
+ * The current remove operation could not be completed; the face template
+ * provided could not be removed.
+ */
+ UNABLE_TO_REMOVE = 6,
+
+ /**
+ * Face authentication is locked out due to too many unsuccessful attempts.
+ */
+ LOCKOUT = 7,
+
+ /**
+ * Used to enable a vendor-specific error message.
+ */
+ VENDOR = 8,
+};
+
+/**
+ * Face acquisition information provides feedback for the current enrollment
+ * or authentication operation.
+ *
+ * This information indicates that the user can take immediate action to resolve
+ * an issue, and clients must ensure that this information is surfaced to the
+ * user.
+ */
+enum FaceAcquiredInfo : int32_t {
+
+ /**
+ * The face acquired was good; no further user interaction is necessary.
+ */
+ GOOD = 0,
+
+ /**
+ * The face data acquired was too noisy or did not have sufficient detail.
+ * This is a catch-all for all acquisition errors not captured by the other
+ * constants.
+ */
+ INSUFFICIENT = 1,
+
+ /**
+ * Because there was too much ambient light, the captured face data was too
+ * bright. It's reasonable to return this after multiple
+ * FaceAcquiredInfo.INSUFFICIENT.
+ *
+ * The user is expected to take action to retry the operation in better
+ * lighting conditions when this is returned.
+ */
+ TOO_BRIGHT = 2,
+
+ /**
+ * Because there was not enough illumination, the captured face data was too
+ * dark. It's reasonable to return this after multiple
+ * FaceAcquiredInfo.INSUFFICIENT.
+ *
+ * The user is expected to take action to retry the operation in better
+ * lighting conditions when this is returned.
+ */
+ TOO_DARK = 3,
+
+ /**
+ * The detected face is too close to the sensor, and the image cannot be
+ * processed.
+ *
+ * The user is expected to be informed to move further from the sensor when
+ * this is returned.
+ */
+ TOO_CLOSE = 4,
+
+ /**
+ * The detected face is too small, as the user might be too far away from
+ * the sensor.
+ *
+ * The user is expected to be informed to move closer to the sensor when
+ * this is returned.
+ */
+ TOO_FAR = 5,
+
+ /**
+ * Only the upper part of the face was detected. The sensor's field of view
+ * is too high.
+ *
+ * The user should be informed to move up with respect to the sensor when
+ * this is returned.
+ */
+ FACE_TOO_HIGH = 6,
+
+ /**
+ * Only the lower part of the face was detected. The sensor's field of view
+ * is too low.
+ *
+ * The user should be informed to move down with respect to the sensor when
+ * this is returned.
+ */
+ FACE_TOO_LOW = 7,
+
+ /**
+ * Only the right part of the face was detected. The sensor's field of view
+ * is too far right.
+ *
+ * The user should be informed to move to the right with respect to the
+ * sensor when this is returned.
+ */
+ FACE_TOO_RIGHT = 8,
+
+ /**
+ * Only the left part of the face was detected. The sensor's field of view
+ * is too far left.
+ *
+ * The user should be informed to move to the left with respect to the
+ * sensor when this is returned.
+ */
+ FACE_TOO_LEFT = 9,
+
+ /**
+ * The user's face was directed away from the sensor. The user should be
+ * informed to face the sensor when this is returned.
+ */
+ POOR_GAZE = 10,
+
+ /**
+ * No face was detected within the sensor's field of view.
+ *
+ * The user should be informed to point the sensor to a face when this is
+ * returned.
+ */
+ NOT_DETECTED = 11,
+
+ /**
+ * Too much motion was detected.
+ *
+ * The user should be informed to keep their face steady relative to the
+ * sensor.
+ */
+ TOO_MUCH_MOTION = 12,
+
+ /**
+ * The sensor needs to be recalibrated.
+ */
+ RECALIBRATE = 13,
+
+ /**
+ * Used to enable a vendor-specific acquisition message.
+ */
+ VENDOR = 14
+};
+
+/**
+ * Result structure with an additional uint64_t field. See documentation in
+ * setCallback(), preEnroll(), and getAuthenticatorId() for usage of the value.
+ */
+struct OptionalUint64 {
+ /**
+ * The return status.
+ */
+ Status status;
+
+ /**
+ * This value is only meaningful if status is OK.
+ */
+ uint64_t value;
+};
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 094b35d..4e610a7 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -70,6 +70,18 @@
include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/clear_vars.mk
+LOCAL_MODULE := framework_compatibility_matrix.current.xml
+LOCAL_MODULE_STEM := compatibility_matrix.current.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_KERNEL_CONFIG_DATA_PATHS := \
+ 4.4.0:$(my_kernel_config_data)/android-4.4 \
+ 4.9.0:$(my_kernel_config_data)/android-4.9 \
+ 4.14.0:$(my_kernel_config_data)/android-4.14 \
+
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
my_kernel_config_data :=
# Framework Compatibility Matrix (common to all FCM versions)
@@ -120,6 +132,7 @@
framework_compatibility_matrix.1.xml \
framework_compatibility_matrix.2.xml \
framework_compatibility_matrix.3.xml \
+ framework_compatibility_matrix.current.xml \
framework_compatibility_matrix.device.xml
# Phony target that installs all framework compatibility matrix files
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
new file mode 100644
index 0000000..1b9ab33
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -0,0 +1,458 @@
+<compatibility-matrix version="1.0" type="framework" level="4">
+ <hal format="hidl" optional="false">
+ <name>android.hardware.audio</name>
+ <version>4.0</version>
+ <interface>
+ <name>IDevicesFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.audio.effect</name>
+ <version>4.0</version>
+ <interface>
+ <name>IEffectsFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.authsecret</name>
+ <version>1.0</version>
+ <interface>
+ <name>IAuthSecret</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.audiocontrol</name>
+ <version>1.0</version>
+ <interface>
+ <name>IAudioControl</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.evs</name>
+ <version>1.0</version>
+ <interface>
+ <name>IEvsEnumerator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.vehicle</name>
+ <version>2.0</version>
+ <interface>
+ <name>IVehicle</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.biometrics.fingerprint</name>
+ <version>2.1</version>
+ <interface>
+ <name>IBiometricsFingerprint</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.bluetooth</name>
+ <version>1.0</version>
+ <interface>
+ <name>IBluetoothHci</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.bluetooth.a2dp</name>
+ <version>1.0</version>
+ <interface>
+ <name>IBluetoothAudioOffload</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.boot</name>
+ <version>1.0</version>
+ <interface>
+ <name>IBootControl</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.broadcastradio</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IBroadcastRadioFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.camera.provider</name>
+ <version>2.4</version>
+ <interface>
+ <name>ICameraProvider</name>
+ <regex-instance>[^/]+/[0-9]+</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.cas</name>
+ <version>1.0</version>
+ <interface>
+ <name>IMediaCasService</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.configstore</name>
+ <version>1.1</version>
+ <interface>
+ <name>ISurfaceFlingerConfigs</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.confirmationui</name>
+ <version>1.0</version>
+ <interface>
+ <name>IConfirmationUI</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.contexthub</name>
+ <version>1.0</version>
+ <interface>
+ <name>IContexthub</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.drm</name>
+ <version>1.0</version>
+ <interface>
+ <name>ICryptoFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ <interface>
+ <name>IDrmFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.drm</name>
+ <version>1.1</version>
+ <interface>
+ <name>ICryptoFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ <interface>
+ <name>IDrmFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.dumpstate</name>
+ <version>1.0</version>
+ <interface>
+ <name>IDumpstateDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.gatekeeper</name>
+ <version>1.0</version>
+ <interface>
+ <name>IGatekeeper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.gnss</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IGnss</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.graphics.allocator</name>
+ <version>2.0</version>
+ <interface>
+ <name>IAllocator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.graphics.composer</name>
+ <version>2.1</version>
+ <interface>
+ <name>IComposer</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.graphics.mapper</name>
+ <version>2.0</version>
+ <interface>
+ <name>IMapper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.health</name>
+ <version>2.0</version>
+ <interface>
+ <name>IHealth</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.ir</name>
+ <version>1.0</version>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.keymaster</name>
+ <version>3.0</version>
+ <version>4.0</version>
+ <interface>
+ <name>IKeymasterDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.keymaster</name>
+ <version>4.0</version>
+ <interface>
+ <name>IKeymasterDevice</name>
+ <instance>strongbox</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.light</name>
+ <version>2.0</version>
+ <interface>
+ <name>ILight</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.media.omx</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOmx</name>
+ <instance>default</instance>
+ </interface>
+ <interface>
+ <name>IOmxStore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.memtrack</name>
+ <version>1.0</version>
+ <interface>
+ <name>IMemtrack</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.neuralnetworks</name>
+ <version>1.0</version>
+ <interface>
+ <name>IDevice</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.nfc</name>
+ <version>1.1</version>
+ <interface>
+ <name>INfc</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.oemlock</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOemLock</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.power</name>
+ <version>1.0-2</version>
+ <interface>
+ <name>IPower</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.radio</name>
+ <version>1.0-2</version>
+ <interface>
+ <name>IRadio</name>
+ <instance>slot1</instance>
+ <instance>slot2</instance>
+ <instance>slot3</instance>
+ </interface>
+ <interface>
+ <name>ISap</name>
+ <instance>slot1</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.radio.config</name>
+ <version>1.0</version>
+ <interface>
+ <name>IRadioConfig</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.renderscript</name>
+ <version>1.0</version>
+ <interface>
+ <name>IDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.secure_element</name>
+ <version>1.0</version>
+ <interface>
+ <name>ISecureElement</name>
+ <regex-instance>eSE[1-9][0-9]*</regex-instance>
+ <regex-instance>SIM[1-9][0-9]*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.sensors</name>
+ <version>1.0</version>
+ <interface>
+ <name>ISensors</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.soundtrigger</name>
+ <version>2.0-1</version>
+ <interface>
+ <name>ISoundTriggerHw</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.tetheroffload.config</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOffloadConfig</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.tetheroffload.control</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOffloadControl</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.thermal</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IThermal</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.tv.cec</name>
+ <version>1.0</version>
+ <interface>
+ <name>IHdmiCec</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.tv.input</name>
+ <version>1.0</version>
+ <interface>
+ <name>ITvInput</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.usb</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IUsb</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.usb.gadget</name>
+ <version>1.0</version>
+ <interface>
+ <name>IUsbGadget</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.vibrator</name>
+ <version>1.0-2</version>
+ <interface>
+ <name>IVibrator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.vr</name>
+ <version>1.0</version>
+ <interface>
+ <name>IVr</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.weaver</name>
+ <version>1.0</version>
+ <interface>
+ <name>IWeaver</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.wifi</name>
+ <version>1.0-2</version>
+ <interface>
+ <name>IWifi</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.wifi.hostapd</name>
+ <version>1.0</version>
+ <interface>
+ <name>IHostapd</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.wifi.offload</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOffload</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.wifi.supplicant</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>ISupplicant</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</compatibility-matrix>
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index 010a46d..608ee70 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -472,6 +472,16 @@
}
}
+/*
+ * SchedulingCapabilities:
+ * Verifies that 2018+ hardware supports Scheduling capabilities.
+ */
+TEST_F(GnssHalTest, SchedulingCapabilities) {
+ if (info_called_count_ > 0 && last_info_.yearOfHw >= 2018) {
+ EXPECT_TRUE(last_capabilities_ & IGnssCallback::Capabilities::SCHEDULING);
+ }
+}
+
int main(int argc, char** argv) {
::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 2f531b4..43a5378 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -25,21 +25,19 @@
namespace V2_1 {
namespace vts {
-Composer::Composer() {
- mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
- init();
-}
+Composer::Composer() : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>()) {}
-Composer::Composer(const std::string& name) {
- mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
- init();
-}
+Composer::Composer(const std::string& name)
+ : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name)) {}
-void Composer::init() {
- ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
+Composer::Composer(const sp<IComposer>& composer) : mComposer(composer) {
+ // ASSERT_* can only be used in functions returning void.
+ [this] {
+ ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
- std::vector<IComposer::Capability> capabilities = getCapabilities();
- mCapabilities.insert(capabilities.begin(), capabilities.end());
+ std::vector<IComposer::Capability> capabilities = getCapabilities();
+ mCapabilities.insert(capabilities.begin(), capabilities.end());
+ }();
}
sp<IComposer> Composer::getRaw() const {
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
index 8d5493e..c97be76 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -57,10 +57,10 @@
std::unique_ptr<ComposerClient> createClient();
protected:
- sp<IComposer> mComposer;
+ explicit Composer(const sp<IComposer>& composer);
private:
- void init();
+ const sp<IComposer> mComposer;
std::unordered_set<IComposer::Capability> mCapabilities;
};
@@ -68,7 +68,7 @@
// A wrapper to IComposerClient.
class ComposerClient {
public:
- ComposerClient(const sp<IComposerClient>& client);
+ explicit ComposerClient(const sp<IComposerClient>& client);
~ComposerClient();
sp<IComposerClient> getRaw() const;
@@ -116,7 +116,7 @@
std::unordered_map<Display, DisplayResource> mDisplayResources;
private:
- sp<IComposerClient> mClient;
+ const sp<IComposerClient> mClient;
};
} // namespace vts
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index 6a32071..f2596a4 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -27,32 +27,31 @@
namespace V2_2 {
namespace vts {
-using android::hardware::details::canCastInterface;
-using android::hardware::details::getDescriptor;
-using android::hardware::graphics::composer::V2_2::IComposerClient;
+using details::canCastInterface;
+using details::getDescriptor;
-std::unique_ptr<ComposerClient_v2_2> Composer_v2_2::createClient_v2_2() {
- std::unique_ptr<ComposerClient_v2_2> client;
- mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
+std::unique_ptr<ComposerClient> Composer::createClient() {
+ std::unique_ptr<ComposerClient> client;
+ getRaw()->createClient([&](const auto& tmpError, const auto& tmpClient) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
ALOGV("tmpClient is a %s", getDescriptor(&(*tmpClient)).c_str());
ASSERT_TRUE(canCastInterface(
&(*tmpClient), "android.hardware.graphics.composer@2.2::IComposerClient", false))
<< "Cannot create 2.2 IComposerClient";
- client = std::make_unique<ComposerClient_v2_2>(IComposerClient::castFrom(tmpClient, true));
+ client = std::make_unique<ComposerClient>(IComposerClient::castFrom(tmpClient, true));
});
return client;
}
-sp<V2_2::IComposerClient> ComposerClient_v2_2::getRaw() const {
- return mClient_v2_2;
+sp<IComposerClient> ComposerClient::getRaw() const {
+ return mClient;
}
-std::vector<IComposerClient::PerFrameMetadataKey> ComposerClient_v2_2::getPerFrameMetadataKeys(
+std::vector<IComposerClient::PerFrameMetadataKey> ComposerClient::getPerFrameMetadataKeys(
Display display) {
std::vector<IComposerClient::PerFrameMetadataKey> keys;
- mClient_v2_2->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) {
+ mClient->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR metadata keys";
keys = tmpKeys;
});
@@ -60,43 +59,42 @@
return keys;
}
-void ComposerClient_v2_2::execute_v2_2(V2_1::vts::TestCommandReader* reader,
- V2_2::CommandWriterBase* writer) {
+void ComposerClient::execute(V2_1::vts::TestCommandReader* reader, CommandWriterBase* writer) {
bool queueChanged = false;
uint32_t commandLength = 0;
hidl_vec<hidl_handle> commandHandles;
ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
if (queueChanged) {
- auto ret = mClient_v2_2->setInputCommandQueue(*writer->getMQDescriptor());
+ auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
return;
}
- mClient_v2_2->executeCommands(commandLength, commandHandles,
- [&](const auto& tmpError, const auto& tmpOutQueueChanged,
- const auto& tmpOutLength, const auto& tmpOutHandles) {
- ASSERT_EQ(Error::NONE, tmpError);
+ mClient->executeCommands(commandLength, commandHandles,
+ [&](const auto& tmpError, const auto& tmpOutQueueChanged,
+ const auto& tmpOutLength, const auto& tmpOutHandles) {
+ ASSERT_EQ(Error::NONE, tmpError);
- if (tmpOutQueueChanged) {
- mClient_v2_2->getOutputCommandQueue(
- [&](const auto& tmpError, const auto& tmpDescriptor) {
- ASSERT_EQ(Error::NONE, tmpError);
- reader->setMQDescriptor(tmpDescriptor);
- });
- }
+ if (tmpOutQueueChanged) {
+ mClient->getOutputCommandQueue(
+ [&](const auto& tmpError, const auto& tmpDescriptor) {
+ ASSERT_EQ(Error::NONE, tmpError);
+ reader->setMQDescriptor(tmpDescriptor);
+ });
+ }
- ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
- reader->parse();
- });
+ ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
+ reader->parse();
+ });
}
-Display ComposerClient_v2_2::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
- PixelFormat formatHint,
- uint32_t outputBufferSlotCount,
- PixelFormat* outFormat) {
+Display ComposerClient::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
+ PixelFormat formatHint,
+ uint32_t outputBufferSlotCount,
+ PixelFormat* outFormat) {
Display display = 0;
- mClient_v2_2->createVirtualDisplay_2_2(
+ mClient->createVirtualDisplay_2_2(
width, height, formatHint, outputBufferSlotCount,
[&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
@@ -110,29 +108,27 @@
return display;
}
-bool ComposerClient_v2_2::getClientTargetSupport_2_2(Display display, uint32_t width,
- uint32_t height, PixelFormat format,
- Dataspace dataspace) {
- Error error =
- mClient_v2_2->getClientTargetSupport_2_2(display, width, height, format, dataspace);
+bool ComposerClient::getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+ PixelFormat format, Dataspace dataspace) {
+ Error error = mClient->getClientTargetSupport_2_2(display, width, height, format, dataspace);
return error == Error::NONE;
}
-void ComposerClient_v2_2::setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode) {
- Error error = mClient_v2_2->setPowerMode_2_2(display, mode);
+void ComposerClient::setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) {
+ Error error = mClient->setPowerMode_2_2(display, mode);
ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set power mode";
}
-void ComposerClient_v2_2::setReadbackBuffer(Display display, const native_handle_t* buffer,
- int32_t /* releaseFence */) {
+void ComposerClient::setReadbackBuffer(Display display, const native_handle_t* buffer,
+ int32_t /* releaseFence */) {
// Ignoring fence, HIDL doesn't care
- Error error = mClient_v2_2->setReadbackBuffer(display, buffer, nullptr);
+ Error error = mClient->setReadbackBuffer(display, buffer, nullptr);
ASSERT_EQ(Error::NONE, error) << "failed to setReadbackBuffer";
}
-void ComposerClient_v2_2::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
- Dataspace* outDataspace) {
- mClient_v2_2->getReadbackBufferAttributes(
+void ComposerClient::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
+ Dataspace* outDataspace) {
+ mClient->getReadbackBufferAttributes(
display,
[&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback buffer attributes";
@@ -141,42 +137,41 @@
});
}
-void ComposerClient_v2_2::getReadbackBufferFence(Display display, int32_t* outFence) {
+void ComposerClient::getReadbackBufferFence(Display display, int32_t* outFence) {
hidl_handle handle;
- mClient_v2_2->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) {
+ mClient->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback fence";
handle = tmpHandle;
});
*outFence = 0;
}
-std::vector<ColorMode> ComposerClient_v2_2::getColorModes(Display display) {
+std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
std::vector<ColorMode> modes;
- mClient_v2_2->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) {
+ mClient->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get color modes";
modes = tmpModes;
});
return modes;
}
-std::vector<RenderIntent> ComposerClient_v2_2::getRenderIntents(Display display, ColorMode mode) {
+std::vector<RenderIntent> ComposerClient::getRenderIntents(Display display, ColorMode mode) {
std::vector<RenderIntent> intents;
- mClient_v2_2->getRenderIntents(
- display, mode, [&](const auto& tmpError, const auto& tmpIntents) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents";
- intents = tmpIntents;
- });
+ mClient->getRenderIntents(display, mode, [&](const auto& tmpError, const auto& tmpIntents) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents";
+ intents = tmpIntents;
+ });
return intents;
}
-void ComposerClient_v2_2::setColorMode(Display display, ColorMode mode, RenderIntent intent) {
- Error error = mClient_v2_2->setColorMode_2_2(display, mode, intent);
+void ComposerClient::setColorMode(Display display, ColorMode mode, RenderIntent intent) {
+ Error error = mClient->setColorMode_2_2(display, mode, intent);
ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set color mode";
}
-std::array<float, 16> ComposerClient_v2_2::getDataspaceSaturationMatrix(Dataspace dataspace) {
+std::array<float, 16> ComposerClient::getDataspaceSaturationMatrix(Dataspace dataspace) {
std::array<float, 16> matrix;
- mClient_v2_2->getDataspaceSaturationMatrix(
+ mClient->getDataspaceSaturationMatrix(
dataspace, [&](const auto& tmpError, const auto& tmpMatrix) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get datasapce saturation matrix";
std::copy_n(tmpMatrix.data(), matrix.size(), matrix.begin());
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 1c6d7ae..2633021 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -36,36 +36,31 @@
namespace V2_2 {
namespace vts {
-using android::hardware::graphics::common::V1_0::Hdr;
-using android::hardware::graphics::common::V1_1::ColorMode;
-using android::hardware::graphics::common::V1_1::Dataspace;
-using android::hardware::graphics::common::V1_1::PixelFormat;
-using android::hardware::graphics::common::V1_1::RenderIntent;
-using android::hardware::graphics::composer::V2_2::IComposer;
-using android::hardware::graphics::composer::V2_2::IComposerClient;
+using common::V1_0::Hdr;
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
-class ComposerClient_v2_2;
+class ComposerClient;
-// Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient
-// Everything else is the same
-class Composer_v2_2 : public V2_1::vts::Composer {
+// A wrapper to IComposer.
+class Composer : public V2_1::vts::Composer {
public:
- Composer_v2_2() : V2_1::vts::Composer(){};
- explicit Composer_v2_2(const std::string& name) : V2_1::vts::Composer(name){};
+ using V2_1::vts::Composer::Composer;
- std::unique_ptr<ComposerClient_v2_2> createClient_v2_2();
+ std::unique_ptr<ComposerClient> createClient();
};
// A wrapper to IComposerClient.
-class ComposerClient_v2_2
- : public android::hardware::graphics::composer::V2_1::vts::ComposerClient {
+class ComposerClient : public V2_1::vts::ComposerClient {
public:
- ComposerClient_v2_2(const sp<IComposerClient>& client)
- : V2_1::vts::ComposerClient(client), mClient_v2_2(client){};
+ explicit ComposerClient(const sp<IComposerClient>& client)
+ : V2_1::vts::ComposerClient(client), mClient(client) {}
- sp<V2_2::IComposerClient> getRaw() const;
+ sp<IComposerClient> getRaw() const;
- void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
+ void execute(V2_1::vts::TestCommandReader* reader, CommandWriterBase* writer);
std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
@@ -73,7 +68,7 @@
uint32_t outputBufferSlotCount, PixelFormat* outFormat);
bool getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
PixelFormat format, Dataspace dataspace);
- void setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode);
+ void setPowerMode_2_2(Display display, IComposerClient::PowerMode mode);
void setReadbackBuffer(Display display, const native_handle_t* buffer, int32_t releaseFence);
void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
Dataspace* outDataspace);
@@ -86,7 +81,7 @@
std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace);
private:
- sp<V2_2::IComposerClient> mClient_v2_2;
+ const sp<IComposerClient> mClient;
};
} // namespace vts
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 23bf558..e3b7f55 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -32,17 +32,15 @@
namespace vts {
namespace {
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_1::ColorMode;
-using android::hardware::graphics::common::V1_1::Dataspace;
-using android::hardware::graphics::common::V1_1::PixelFormat;
-using android::hardware::graphics::common::V1_1::RenderIntent;
-using android::hardware::graphics::composer::V2_2::IComposerClient;
-using android::hardware::graphics::mapper::V2_1::IMapper;
-using android::hardware::graphics::mapper::V2_1::vts::Gralloc;
-using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
+using common::V1_0::BufferUsage;
+using common::V1_0::ColorTransform;
+using common::V1_0::Transform;
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
+using mapper::V2_1::IMapper;
+using mapper::V2_1::vts::Gralloc;
// Test environment for graphics.composer
class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
@@ -65,9 +63,9 @@
protected:
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(
- mComposer = std::make_unique<Composer_v2_2>(
+ mComposer = std::make_unique<Composer>(
GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
- ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2());
+ ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
mComposerClient->registerCallback(mComposerCallback);
@@ -96,8 +94,8 @@
// use the slot count usually set by SF
static constexpr uint32_t kBufferSlotCount = 64;
- std::unique_ptr<Composer_v2_2> mComposer;
- std::unique_ptr<ComposerClient_v2_2> mComposerClient;
+ std::unique_ptr<Composer> mComposer;
+ std::unique_ptr<ComposerClient> mComposerClient;
sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
// the first display and is assumed never to be removed
Display mPrimaryDisplay;
@@ -125,7 +123,7 @@
ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
- mWriter = std::make_unique<V2_2::CommandWriterBase>(1024);
+ mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<V2_1::vts::TestCommandReader>();
}
@@ -143,9 +141,9 @@
return mGralloc->allocate(info);
}
- void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); }
+ void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
- std::unique_ptr<V2_2::CommandWriterBase> mWriter;
+ std::unique_ptr<CommandWriterBase> mWriter;
std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
private:
diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp
new file mode 100644
index 0000000..23061dd
--- /dev/null
+++ b/graphics/composer/2.3/Android.bp
@@ -0,0 +1,21 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.graphics.composer@2.3",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "IComposer.hal",
+ "IComposerClient.hal",
+ ],
+ interfaces: [
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
+
diff --git a/graphics/composer/2.3/IComposer.hal b/graphics/composer/2.3/IComposer.hal
new file mode 100644
index 0000000..90b2427
--- /dev/null
+++ b/graphics/composer/2.3/IComposer.hal
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer@2.3;
+
+import IComposerClient;
+
+import @2.1::Error;
+import @2.2::IComposer;
+
+interface IComposer extends @2.2::IComposer {
+
+ /**
+ * Creates a v2.3 client of the composer. Supersedes @2.1::createClient.
+ *
+ * @return error is NONE upon success. Otherwise,
+ * NO_RESOURCES when the client could not be created.
+ * @return client is the newly created client.
+ */
+ @entry
+ @callflow(next="*")
+ createClient_2_3() generates (Error error, IComposerClient client);
+
+};
diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal
new file mode 100644
index 0000000..77dd3ee
--- /dev/null
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer@2.3;
+
+import @2.2::IComposerClient;
+import @2.1::Display;
+import @2.1::Error;
+
+interface IComposerClient extends @2.2::IComposerClient {
+
+ /**
+ * Returns the port and data that describe a physical display. The port is
+ * a unique number that identifies a physical connector (e.g. eDP, HDMI)
+ * for display output. The data blob is parsed to determine its format,
+ * typically EDID 1.3 as specified in VESA E-EDID Standard Release A
+ * Revision 1.
+ *
+ * @param display is the display to query.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_DISPLAY when an invalid display handle was passed in.
+ * UNSUPPORTED when identification data is unavailable.
+ * @return port is the connector to which the display is connected.
+ * @return data is the EDID 1.3 blob identifying the display.
+ */
+ @callflow(next="*")
+ getDisplayIdentificationData(Display display)
+ generates (Error error,
+ uint8_t port,
+ vec<uint8_t> data);
+
+};
diff --git a/graphics/composer/2.3/default/Android.bp b/graphics/composer/2.3/default/Android.bp
new file mode 100644
index 0000000..ad49ec3
--- /dev/null
+++ b/graphics/composer/2.3/default/Android.bp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2018 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_binary {
+ name: "android.hardware.graphics.composer@2.3-service",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["service.cpp"],
+ init_rc: ["android.hardware.graphics.composer@2.3-service.rc"],
+ header_libs: [
+ "android.hardware.graphics.composer@2.3-passthrough",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
+ "android.hardware.graphics.mapper@2.0",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+}
diff --git a/graphics/composer/2.3/default/OWNERS b/graphics/composer/2.3/default/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/composer/2.3/default/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
new file mode 100644
index 0000000..08e32d8
--- /dev/null
+++ b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
@@ -0,0 +1,6 @@
+service vendor.hwcomposer-2-3 /vendor/bin/hw/android.hardware.graphics.composer@2.3-service
+ class hal animation
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
diff --git a/graphics/composer/2.3/default/service.cpp b/graphics/composer/2.3/default/service.cpp
new file mode 100644
index 0000000..347d8be
--- /dev/null
+++ b/graphics/composer/2.3/default/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 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 <sched.h>
+
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <binder/ProcessState.h>
+#include <composer-passthrough/2.3/HwcLoader.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::graphics::composer::V2_3::IComposer;
+using android::hardware::graphics::composer::V2_3::passthrough::HwcLoader;
+
+int main() {
+ // the conventional HAL might start binder services
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
+ android::ProcessState::self()->startThreadPool();
+
+ // same as SF main thread
+ struct sched_param param = {0};
+ param.sched_priority = 2;
+ if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) {
+ ALOGE("Couldn't set SCHED_FIFO: %d", errno);
+ }
+
+ android::hardware::configureRpcThreadpool(4, true /* will join */);
+
+ android::sp<IComposer> composer = HwcLoader::load();
+ if (composer == nullptr) {
+ return 1;
+ }
+ if (composer->registerAsService() != android::NO_ERROR) {
+ ALOGE("failed to register service");
+ return 1;
+ }
+
+ android::hardware::joinRpcThreadpool();
+
+ ALOGE("service is terminating");
+ return 1;
+}
diff --git a/graphics/composer/2.3/utils/OWNERS b/graphics/composer/2.3/utils/OWNERS
new file mode 100644
index 0000000..234bc75
--- /dev/null
+++ b/graphics/composer/2.3/utils/OWNERS
@@ -0,0 +1,7 @@
+# Graphics team
+olv@google.com
+stoza@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
diff --git a/graphics/composer/2.3/utils/hal/Android.bp b/graphics/composer/2.3/utils/hal/Android.bp
new file mode 100644
index 0000000..aa46df1
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2018 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_headers {
+ name: "android.hardware.graphics.composer@2.3-hal",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.3",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.3",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.2-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h
new file mode 100644
index 0000000..8e11a5a
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Composer.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <composer-hal/2.2/Composer.h>
+#include <composer-hal/2.3/ComposerClient.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public V2_2::hal::detail::ComposerImpl<Interface, Hal> {
+ public:
+ static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
+ return std::make_unique<ComposerImpl>(std::move(hal));
+ }
+
+ explicit ComposerImpl(std::unique_ptr<Hal> hal) : BaseType2_2(std::move(hal)) {}
+
+ // IComposer 2.3 interface
+
+ Return<void> createClient_2_3(IComposer::createClient_2_3_cb hidl_cb) override {
+ std::unique_lock<std::mutex> lock(mClientMutex);
+ if (!waitForClientDestroyedLocked(lock)) {
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ sp<ComposerClient> client = ComposerClient::create(mHal.get()).release();
+ if (!client) {
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ auto clientDestroyed = [this]() { onClientDestroyed(); };
+ client->setOnClientDestroyed(clientDestroyed);
+
+ mClient = client;
+ hidl_cb(Error::NONE, client);
+ return Void();
+ }
+
+ private:
+ using BaseType2_2 = V2_2::hal::detail::ComposerImpl<Interface, Hal>;
+ using BaseType2_1 = V2_1::hal::detail::ComposerImpl<Interface, Hal>;
+
+ using BaseType2_1::mClient;
+ using BaseType2_1::mClientMutex;
+ using BaseType2_1::mHal;
+ using BaseType2_1::onClientDestroyed;
+ using BaseType2_1::waitForClientDestroyedLocked;
+};
+
+} // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
new file mode 100644
index 0000000..e717d84
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "ComposerClient.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
+#include <composer-hal/2.3/ComposerClient.h>
+#include <composer-hal/2.3/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl<Interface, Hal> {
+ public:
+ static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
+ auto client = std::make_unique<ComposerClientImpl>(hal);
+ return client->init() ? std::move(client) : nullptr;
+ }
+
+ ComposerClientImpl(Hal* hal) : BaseType2_2(hal) {}
+
+ // IComposerClient 2.3 interface
+
+ Return<void> getDisplayIdentificationData(
+ Display display, IComposerClient::getDisplayIdentificationData_cb hidl_cb) override {
+ uint8_t port = 0;
+ std::vector<uint8_t> data;
+ Error error = mHal->getDisplayIdentificationData(display, &port, &data);
+ hidl_cb(error, port, data);
+ return Void();
+ }
+
+ private:
+ using BaseType2_2 = V2_2::hal::detail::ComposerClientImpl<Interface, Hal>;
+ using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
+
+ using BaseType2_1::mHal;
+};
+
+} // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
new file mode 100644
index 0000000..37ea0a3
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <composer-hal/2.2/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace hal {
+
+using V2_1::Display;
+using V2_1::Error;
+
+class ComposerHal : public V2_2::hal::ComposerHal {
+ public:
+ virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) = 0;
+};
+
+} // namespace hal
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/passthrough/Android.bp b/graphics/composer/2.3/utils/passthrough/Android.bp
new file mode 100644
index 0000000..3ae6b16
--- /dev/null
+++ b/graphics/composer/2.3/utils/passthrough/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2018 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_headers {
+ name: "android.hardware.graphics.composer@2.3-passthrough",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-passthrough",
+ "android.hardware.graphics.composer@2.3-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.2-passthrough",
+ "android.hardware.graphics.composer@2.3-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
new file mode 100644
index 0000000..53f2d1b
--- /dev/null
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <type_traits>
+
+#include <composer-hal/2.3/ComposerHal.h>
+#include <composer-passthrough/2.2/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace passthrough {
+
+namespace detail {
+
+using V2_1::Display;
+using V2_1::Error;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
+ public:
+ Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) override {
+ if (!mDispatch.getDisplayIdentificationData) {
+ return Error::UNSUPPORTED;
+ }
+
+ uint32_t size = 0;
+ int32_t error =
+ mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ std::vector<uint8_t> data(size);
+ error =
+ mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, data.data());
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ data.resize(size);
+ *outData = std::move(data);
+ return Error::NONE;
+ }
+
+ protected:
+ bool initDispatch() override {
+ if (!BaseType2_2::initDispatch()) {
+ return false;
+ }
+
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA,
+ &mDispatch.getDisplayIdentificationData);
+ return true;
+ }
+
+ private:
+ struct {
+ HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData;
+ } mDispatch = {};
+
+ using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1::mDevice;
+};
+
+} // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+} // namespace passthrough
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h
new file mode 100644
index 0000000..afef475
--- /dev/null
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <composer-hal/2.3/Composer.h>
+#include <composer-hal/2.3/ComposerHal.h>
+#include <composer-passthrough/2.2/HwcLoader.h>
+#include <composer-passthrough/2.3/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace passthrough {
+
+class HwcLoader : public V2_2::passthrough::HwcLoader {
+ public:
+ static IComposer* load() {
+ const hw_module_t* module = loadModule();
+ if (!module) {
+ return nullptr;
+ }
+
+ auto hal = createHalWithAdapter(module);
+ if (!hal) {
+ return nullptr;
+ }
+
+ return createComposer(std::move(hal)).release();
+ }
+
+ // create a ComposerHal instance
+ static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+
+ // create a ComposerHal instance, insert an adapter if necessary
+ static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+ bool adapted;
+ hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+ if (!device) {
+ return nullptr;
+ }
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+ }
+
+ // create an IComposer instance
+ static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+ return hal::Composer::create(std::move(hal));
+ }
+};
+
+} // namespace passthrough
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp
new file mode 100644
index 0000000..0553258
--- /dev/null
+++ b/graphics/composer/2.3/utils/vts/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2018 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_static {
+ name: "android.hardware.graphics.composer@2.3-vts",
+ defaults: ["hidl_defaults"],
+ srcs: [
+ "ComposerVts.cpp",
+ ],
+ static_libs: [
+ "VtsHalHidlTargetTestBase",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.1-vts",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.2-vts",
+ "android.hardware.graphics.composer@2.3",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ ],
+ cflags: [
+ "-O0",
+ "-g",
+ "-DLOG_TAG=\"ComposerVts\"",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
new file mode 100644
index 0000000..f1d3a50
--- /dev/null
+++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 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 <composer-vts/2.3/ComposerVts.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace vts {
+
+using V2_1::Error;
+
+Composer::Composer() : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>()) {}
+
+Composer::Composer(const std::string& name)
+ : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name)) {}
+
+Composer::Composer(const sp<IComposer>& composer)
+ : V2_2::vts::Composer(composer), mComposer(composer) {}
+
+std::unique_ptr<ComposerClient> Composer::createClient() {
+ std::unique_ptr<ComposerClient> client;
+ mComposer->createClient_2_3([&client](const auto& tmpError, const auto& tmpClient) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
+ client = std::make_unique<ComposerClient>(tmpClient);
+ });
+
+ return client;
+}
+
+bool ComposerClient::getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) {
+ bool supported = true;
+ mClient->getDisplayIdentificationData(
+ display, [&](const auto& tmpError, const auto& tmpPort, const auto& tmpData) {
+ if (tmpError == Error::UNSUPPORTED) {
+ supported = false;
+ return;
+ }
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get display identification data";
+
+ *outPort = tmpPort;
+ *outData = tmpData;
+ ASSERT_FALSE(outData->empty()) << "data is empty";
+ });
+
+ return supported;
+}
+
+} // namespace vts
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
new file mode 100644
index 0000000..103b85a
--- /dev/null
+++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
+#include <composer-vts/2.2/ComposerVts.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace vts {
+
+using V2_1::Display;
+using V2_3::IComposer;
+using V2_3::IComposerClient;
+
+class ComposerClient;
+
+// A wrapper to IComposer.
+class Composer : public V2_2::vts::Composer {
+ public:
+ Composer();
+ explicit Composer(const std::string& name);
+
+ std::unique_ptr<ComposerClient> createClient();
+
+ protected:
+ explicit Composer(const sp<IComposer>& composer);
+
+ private:
+ const sp<IComposer> mComposer;
+};
+
+// A wrapper to IComposerClient.
+class ComposerClient : public V2_2::vts::ComposerClient {
+ public:
+ explicit ComposerClient(const sp<IComposerClient>& client)
+ : V2_2::vts::ComposerClient(client), mClient(client) {}
+
+ bool getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData);
+
+ private:
+ const sp<IComposerClient> mClient;
+};
+
+} // namespace vts
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
new file mode 100644
index 0000000..df696c9
--- /dev/null
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2018 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_test {
+ name: "VtsHalGraphicsComposerV2_3TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
+
+ // TODO(b/64437680): Assume these libs are always available on the device.
+ shared_libs: [
+ "libfmq",
+ "libhidltransport",
+ "libsync",
+ ],
+ static_libs: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.1-vts",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.2-vts",
+ "android.hardware.graphics.composer@2.3",
+ "android.hardware.graphics.composer@2.3-vts",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.0-vts",
+ "android.hardware.graphics.mapper@2.1",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ ],
+}
diff --git a/graphics/composer/2.3/vts/functional/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS
new file mode 100644
index 0000000..234bc75
--- /dev/null
+++ b/graphics/composer/2.3/vts/functional/OWNERS
@@ -0,0 +1,7 @@
+# Graphics team
+olv@google.com
+stoza@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
new file mode 100644
index 0000000..f4e34f0
--- /dev/null
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "graphics_composer_hidl_hal_test@2.3"
+
+#include <algorithm>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.3/ComposerVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace vts {
+namespace {
+
+// Test environment for graphics.composer
+class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static GraphicsComposerHidlEnvironment* Instance() {
+ static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
+ return instance;
+ }
+
+ virtual void registerTestServices() override { registerTestService<IComposer>(); }
+
+ private:
+ GraphicsComposerHidlEnvironment() {}
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
+};
+
+class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(
+ mComposer = std::make_unique<Composer>(
+ GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+ ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+
+ mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
+ mComposerClient->registerCallback(mComposerCallback);
+
+ // assume the first display is primary and is never removed
+ mPrimaryDisplay = waitForFirstDisplay();
+
+ // explicitly disable vsync
+ mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+ mComposerCallback->setVsyncAllowed(false);
+ }
+
+ void TearDown() override {
+ if (mComposerCallback != nullptr) {
+ EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+ }
+ }
+
+ std::unique_ptr<Composer> mComposer;
+ std::unique_ptr<ComposerClient> mComposerClient;
+ sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
+ // the first display and is assumed never to be removed
+ Display mPrimaryDisplay;
+
+ private:
+ Display waitForFirstDisplay() {
+ while (true) {
+ std::vector<Display> displays = mComposerCallback->getDisplays();
+ if (displays.empty()) {
+ usleep(5 * 1000);
+ continue;
+ }
+
+ return displays[0];
+ }
+ }
+};
+
+/**
+ * Test IComposerClient::getDisplayIdentificationData.
+ *
+ * TODO: Check that ports are unique for multiple displays.
+ */
+TEST_F(GraphicsComposerHidlTest, GetDisplayIdentificationData) {
+ uint8_t port0;
+ std::vector<uint8_t> data0;
+ if (mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port0, &data0)) {
+ uint8_t port1;
+ std::vector<uint8_t> data1;
+ ASSERT_TRUE(mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port1, &data1));
+
+ ASSERT_EQ(port0, port1) << "ports are not stable";
+ ASSERT_TRUE(data0.size() == data1.size() &&
+ std::equal(data0.begin(), data0.end(), data1.begin()))
+ << "data is not stable";
+ }
+}
+
+} // namespace
+} // namespace vts
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+int main(int argc, char** argv) {
+ using android::hardware::graphics::composer::V2_3::vts::GraphicsComposerHidlEnvironment;
+ ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ return status;
+}
diff --git a/health/2.0/README b/health/2.0/README
index dfd965a..9f77b83 100644
--- a/health/2.0/README
+++ b/health/2.0/README
@@ -48,16 +48,12 @@
header_libs: ["libhealthd_headers"],
- // Uncomment the following to remove healthd from the build.
- // overrides: [
- // "healthd",
- // ],
+ overrides: [
+ "healthd",
+ ],
}
- 3.1 (recommended) To remove healthd from the build, keep "overrides"
- section, and include the following in device.mk:
- DEVICE_FRAMEWORK_MANIFEST_FILE += \
- system/libhidl/vintfdata/manifest_healthd_exclude.xml
+ 3.1 (recommended) To remove healthd from the build, keep "overrides" section.
3.2 To keep healthd in the build, remove "overrides" section.
4. Create device/<manufacturer>/<device>/health/android.hardware.health@2.0-service.<device>.rc
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index 34a96a0..88a9e26 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -470,7 +470,7 @@
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateExecuting);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
+ status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index c1863d5..1575ba2 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -41,6 +41,8 @@
/* As component is switching states (loaded<->idle<->execute), dequeueMessage()
* expects the events to be received within this duration */
#define DEFAULT_TIMEOUT 100000
+// b/70933963
+#define RELAXED_TIMEOUT 400000
/* Time interval between successive Input/Output enqueues */
#define DEFAULT_TIMEOUT_Q 2000
/* While the component is amidst a process call, asynchronous commands like
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 7750a12..4ddc833 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -1149,15 +1149,13 @@
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
// do not enable the port until all the buffers are supplied
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
- &pBuffer[0], &pBuffer[1]);
+ status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT, &pBuffer[0], &pBuffer[1]);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
omxNode, &pBuffer[i - portBase], i, portMode[i - portBase]));
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
- &pBuffer[0], &pBuffer[1]);
+ status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT, &pBuffer[0], &pBuffer[1]);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index 3bd0557..c4da184 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -111,16 +111,16 @@
bool removeOldFilesInternal() {
time_t now = time(0);
const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
- DIR* dir_dump = opendir(kTombstoneFolderPath);
+ std::unique_ptr<DIR, decltype(&closedir)> dir_dump(
+ opendir(kTombstoneFolderPath), closedir);
if (!dir_dump) {
LOG(ERROR) << "Failed to open directory: " << strerror(errno);
return false;
}
- unique_fd dir_auto_closer(dirfd(dir_dump));
struct dirent* dp;
bool success = true;
std::list<std::pair<const time_t, std::string>> valid_files;
- while ((dp = readdir(dir_dump))) {
+ while ((dp = readdir(dir_dump.get()))) {
if (dp->d_type != DT_REG) {
continue;
}
@@ -246,13 +246,13 @@
size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
struct dirent* dp;
size_t n_error = 0;
- DIR* dir_dump = opendir(input_dir);
+ std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir),
+ closedir);
if (!dir_dump) {
LOG(ERROR) << "Failed to open directory: " << strerror(errno);
return ++n_error;
}
- unique_fd dir_auto_closer(dirfd(dir_dump));
- while ((dp = readdir(dir_dump))) {
+ while ((dp = readdir(dir_dump.get()))) {
if (dp->d_type != DT_REG) {
continue;
}