Merge changes from topics "aae-watchdog-vhal-integration", "aae_new_vhal_healthcheck"
* changes:
Implement VHAL health check
Integrate car watchdog into VHAL
diff --git a/car_product/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml b/car_product/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
index 81a9a3d..5b53dcf 100644
--- a/car_product/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
+++ b/car_product/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
@@ -26,4 +26,7 @@
<!-- Disable system heads-up notifications -->
<integer name="def_heads_up_enabled">0</integer>
+
+ <!-- Default for UI touch sounds disabled -->
+ <bool name="def_sound_effects_enabled">false</bool>
</resources>
diff --git a/cpp/computepipe/tests/fuzz/Android.bp b/cpp/computepipe/tests/fuzz/Android.bp
index fd56ef7..001b97f 100644
--- a/cpp/computepipe/tests/fuzz/Android.bp
+++ b/cpp/computepipe/tests/fuzz/Android.bp
@@ -34,6 +34,7 @@
"-Wall",
"-Werror",
"-Wno-unused-parameter",
+ "-Wno-unused-variable",
],
static_libs: [
"computepipe_runner_component",
@@ -54,6 +55,7 @@
],
header_libs: [
"computepipe_runner_includes",
+ "graph_test_headers",
],
include_dirs: [
"packages/services/Car/cpp/computepipe",
@@ -124,7 +126,6 @@
defaults: ["libcomputepipefuzz-defaults"],
cppflags:[
"-fexceptions",
- "-Wno-unused-variable",
],
static_libs: [
"computepipe_prebuilt_graph",
@@ -140,3 +141,27 @@
"LocalPrebuildGraphFuzzer.cpp",
],
}
+
+cc_fuzz {
+ name: "grpc_graph_fuzzer",
+ defaults: ["libcomputepipefuzz-defaults"],
+ cppflags:[
+ "-fexceptions",
+ ],
+ static_libs: [
+ "computepipe_grpc_graph_proto",
+ ],
+ shared_libs: [
+ "computepipe_grpc_graph",
+ "libcomputepipeprotos",
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ include_dirs: [
+ "packages/services/Car/cpp/computepipe",
+ "packages/services/Car/cpp/computepipe/runner/graph",
+ ],
+ srcs: [
+ "GrpcGraphFuzzer.cpp",
+ ],
+}
diff --git a/cpp/computepipe/tests/fuzz/Common.h b/cpp/computepipe/tests/fuzz/Common.h
index ffaf015..9934b61 100644
--- a/cpp/computepipe/tests/fuzz/Common.h
+++ b/cpp/computepipe/tests/fuzz/Common.h
@@ -33,6 +33,19 @@
HANDLE_RESET_PHASE, /* verify handleResetPhase */ \
API_SUM
+#define GRAPH_RUNNER_BASE_ENUM \
+ GET_GRAPH_TYPE, /* verify GetGraphType */ \
+ GET_GRAPH_STATE, /* verify GetGraphState */ \
+ GET_STATUS, /* verify GetStatus */ \
+ GET_ERROR_MESSAGE, /* verify GetErrorMessage */ \
+ GET_SUPPORTED_GRAPH_CONFIGS, /* verify GetSupportedGraphConfigs */ \
+ SET_INPUT_STREAM_DATA, /* verify SetInputStreamData */ \
+ SET_INPUT_STREAM_PIXEL_DATA, /* verify SetInputStreamPixelData */ \
+ START_GRAPH_PROFILING, /* verify StartGraphProfiling */ \
+ STOP_GRAPH_PROFILING /* verify StopGraphProfiling */
+
+const char kAddress[16] = "[::]:10000";
+
} // namespace test
} // namespace runner
} // namespace computepipe
diff --git a/cpp/computepipe/tests/fuzz/GrpcGraphFuzzer.cpp b/cpp/computepipe/tests/fuzz/GrpcGraphFuzzer.cpp
new file mode 100644
index 0000000..338b3f8
--- /dev/null
+++ b/cpp/computepipe/tests/fuzz/GrpcGraphFuzzer.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <gmock/gmock.h>
+#include "ClientConfig.pb.h"
+#include "Common.h"
+#include "GrpcGraph.h"
+#include "GrpcGraphServerImpl.h"
+
+using ::android::automotive::computepipe::runner::ClientConfig;
+
+namespace android {
+namespace automotive {
+namespace computepipe {
+namespace graph {
+
+namespace {
+
+enum GRPC_GRAPH_FUZZ_FUNCS {
+ GRAPH_RUNNER_BASE_ENUM,
+ DISPATCH_PIXEL_DATA, /* verify dispatchPixelData */
+ DISPATCH_SERIALIZED_DATA, /* dispatchSerializedData */
+ DISPATCH_GRAPH_TERMINATION_MSG, /* dispatchGraphTerminationMessage */
+ RUNNER_COMP_BASE_ENUM
+};
+
+bool DoInitialization() {
+ // Initialization goes here
+ std::shared_ptr<GrpcGraphServerImpl> server;
+ server = std::make_shared<GrpcGraphServerImpl>(runner::test::kAddress);
+ std::thread t = std::thread([server]() { server->startServer(); });
+ t.detach();
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ static bool initialized = DoInitialization();
+ std::shared_ptr<PrebuiltEngineInterfaceImpl> engine;
+ std::unique_ptr<GrpcGraph> graph = std::make_unique<GrpcGraph>();
+ engine = std::make_shared<PrebuiltEngineInterfaceImpl>();
+ Status status = graph->initialize(runner::test::kAddress, engine);
+ if (status != Status::SUCCESS) {
+ LOG(ERROR) << "Initialization of GrpcGraph failed, aborting...";
+ exit(1);
+ }
+
+ // Fuzz goes here
+ FuzzedDataProvider fdp(data, size);
+ while (fdp.remaining_bytes() > runner::test::kMaxFuzzerConsumedBytes) {
+ switch (fdp.ConsumeIntegralInRange<uint32_t>(0, API_SUM - 1)) {
+ case GET_GRAPH_TYPE: {
+ graph->GetGraphType();
+ break;
+ }
+ case GET_GRAPH_STATE: {
+ graph->GetGraphState();
+ break;
+ }
+ case GET_STATUS: {
+ graph->GetStatus();
+ break;
+ }
+ case GET_ERROR_MESSAGE: {
+ graph->GetErrorMessage();
+ break;
+ }
+ case GET_SUPPORTED_GRAPH_CONFIGS: {
+ graph->GetSupportedGraphConfigs();
+ break;
+ }
+ case SET_INPUT_STREAM_DATA: {
+ graph->SetInputStreamData(/*streamIndex =*/2, /* timestamp =*/0, /* data =*/"");
+ break;
+ }
+ case SET_INPUT_STREAM_PIXEL_DATA: {
+ runner::InputFrame inputFrame(0, 0, PixelFormat::RGB, 0, nullptr);
+ graph->SetInputStreamPixelData(/*streamIndex =*/1, /*timestamp =*/0,
+ /*inputFrame =*/inputFrame);
+ break;
+ }
+ case START_GRAPH_PROFILING: {
+ graph->StartGraphProfiling();
+ break;
+ }
+ case STOP_GRAPH_PROFILING: {
+ graph->StopGraphProfiling();
+ break;
+ }
+ case HANDLE_CONFIG_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleConfigPhase(e);
+ break;
+ }
+ case HANDLE_EXECUTION_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleExecutionPhase(e);
+ break;
+ }
+ case HANDLE_STOP_IMMEDIATE_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleStopImmediatePhase(e);
+ break;
+ }
+ case HANDLE_STOP_WITH_FLUSH_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleStopWithFlushPhase(e);
+ break;
+ }
+ case HANDLE_RESET_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleResetPhase(e);
+ break;
+ }
+ case DISPATCH_PIXEL_DATA: {
+ runner::InputFrame inputFrame(0, 0, PixelFormat::RGB, 0, nullptr);
+ graph->dispatchPixelData(/*streamIndex =*/1, /*timestamp =*/0,
+ /*inputFrame =*/inputFrame);
+ break;
+ }
+ case DISPATCH_SERIALIZED_DATA: {
+ graph->dispatchSerializedData(/*streamIndex =*/2, /* timestamp =*/0, /* data =*/"");
+ break;
+ }
+ case DISPATCH_GRAPH_TERMINATION_MSG: {
+ uint8_t status = fdp.ConsumeIntegralInRange<uint8_t>(0, Status::STATUS_MAX - 1);
+ graph->dispatchGraphTerminationMessage(static_cast<Status>(status), "");
+ break;
+ }
+ default:
+ LOG(ERROR) << "Unexpected option aborting...";
+ break;
+ }
+ }
+ return 0;
+}
+
+} // namespace
+} // namespace graph
+} // namespace computepipe
+} // namespace automotive
+} // namespace android
diff --git a/cpp/computepipe/tests/fuzz/LocalPrebuildGraphFuzzer.cpp b/cpp/computepipe/tests/fuzz/LocalPrebuildGraphFuzzer.cpp
index 5d505e0..c7398e4 100644
--- a/cpp/computepipe/tests/fuzz/LocalPrebuildGraphFuzzer.cpp
+++ b/cpp/computepipe/tests/fuzz/LocalPrebuildGraphFuzzer.cpp
@@ -20,7 +20,7 @@
#include "ClientConfig.pb.h"
#include "Common.h"
#include "LocalPrebuiltGraph.h"
-#include "PrebuiltEngineInterface.h"
+#include "PrebuiltEngineInterfaceImpl.h"
using ::android::automotive::computepipe::runner::ClientConfig;
@@ -31,56 +31,7 @@
namespace {
-enum LOCAL_PREBUILD_GRAPH_FUZZ_FUNCS {
- GET_GRAPH_TYPE,
- GET_GRAPH_STATE,
- GET_STATUS,
- GET_ERROR_MESSAGE,
- GET_SUPPORTED_GRAPH_CONFIGS,
- SET_INPUT_STREAM_DATA,
- SET_INPUT_STREAM_PIXEL_DATA,
- START_GRAPH_PROFILING,
- STOP_GRAPH_PROFILING,
- RUNNER_COMP_BASE_ENUM
-};
-
-// Barebones implementation of the PrebuiltEngineInterface. This implementation should suffice for
-// basic cases. More complicated use cases might need their own implementation of it.
-typedef std::function<void(int, int64_t, const runner::InputFrame&)> PixelCallback;
-typedef std::function<void(int, int64_t, std::string&&)> SerializedStreamCallback;
-typedef std::function<void(Status, std::string&&)> GraphTerminationCallback;
-class PrebuiltEngineInterfaceImpl : public PrebuiltEngineInterface {
- private:
- PixelCallback mPixelCallbackFn;
- SerializedStreamCallback mSerializedStreamCallbackFn;
- GraphTerminationCallback mGraphTerminationCallbackFn;
-
- public:
- virtual ~PrebuiltEngineInterfaceImpl() = default;
-
- void DispatchPixelData(int streamId, int64_t timestamp,
- const runner::InputFrame& frame) override {
- mPixelCallbackFn(streamId, timestamp, frame);
- }
-
- void DispatchSerializedData(int streamId, int64_t timestamp, std::string&& data) override {
- mSerializedStreamCallbackFn(streamId, timestamp, std::move(data));
- }
-
- void DispatchGraphTerminationMessage(Status status, std::string&& msg) override {
- mGraphTerminationCallbackFn(status, std::move(msg));
- }
-
- void SetPixelCallback(PixelCallback callback) { mPixelCallbackFn = callback; }
-
- void SetSerializedStreamCallback(SerializedStreamCallback callback) {
- mSerializedStreamCallbackFn = callback;
- }
-
- void SetGraphTerminationCallback(GraphTerminationCallback callback) {
- mGraphTerminationCallbackFn = callback;
- }
-};
+enum LOCAL_PREBUILD_GRAPH_FUZZ_FUNCS { GRAPH_RUNNER_BASE_ENUM, RUNNER_COMP_BASE_ENUM };
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// Initialization goes here
diff --git a/cpp/computepipe/tests/runner/graph/Android.bp b/cpp/computepipe/tests/runner/graph/Android.bp
index 9e973be..60864c2 100644
--- a/cpp/computepipe/tests/runner/graph/Android.bp
+++ b/cpp/computepipe/tests/runner/graph/Android.bp
@@ -12,6 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+cc_library_headers {
+ name: "graph_test_headers",
+ export_include_dirs: ["./includes"],
+}
+
cc_test {
name: "computepipe_prebuilt_graph_test",
test_suites: ["device-tests"],
@@ -24,7 +29,7 @@
"computepipe_runner_component",
"libgtest",
"libgmock",
- "libcomputepipeprotos",
+ "libcomputepipeprotos",
],
shared_libs: [
"libstubgraphimpl",
@@ -35,6 +40,7 @@
],
header_libs: [
"computepipe_runner_includes",
+ "graph_test_headers",
],
include_dirs: [
"packages/services/Car/cpp/computepipe",
@@ -63,7 +69,7 @@
shared_libs: [
"computepipe_grpc_graph",
"libbase",
- "libcomputepipeprotos",
+ "libcomputepipeprotos",
"libgrpc++",
"libdl",
"liblog",
@@ -71,6 +77,7 @@
],
header_libs: [
"computepipe_runner_includes",
+ "graph_test_headers",
],
include_dirs: [
"packages/services/Car/cpp/computepipe",
diff --git a/cpp/computepipe/tests/runner/graph/GrpcGraphTest.cpp b/cpp/computepipe/tests/runner/graph/GrpcGraphTest.cpp
index 2effb00..8a0ddc9 100644
--- a/cpp/computepipe/tests/runner/graph/GrpcGraphTest.cpp
+++ b/cpp/computepipe/tests/runner/graph/GrpcGraphTest.cpp
@@ -22,6 +22,7 @@
#include <grpc++/grpc++.h>
#include "ClientConfig.pb.h"
+#include "GrpcGraphServerImpl.h"
#include "GrpcPrebuiltGraphService.grpc.pb.h"
#include "GrpcPrebuiltGraphService.pb.h"
#include "Options.pb.h"
@@ -44,190 +45,6 @@
namespace graph {
namespace {
-constexpr char kGraphName[] = "Stub graph name";
-constexpr char kSetGraphConfigMessage[] = "Stub set config message";
-constexpr char kSetDebugOptionMessage[] = "Stub set debug option message";
-constexpr char kStartGraphMessage[] = "Stub start graph message";
-constexpr char kStopGraphMessage[] = "Stub stop graph message";
-constexpr char kOutputStreamPacket[] = "Stub output stream packet";
-constexpr char kResetGraphMessage[] = "ResetGraphMessage";
-
-// This is a barebones synchronous server implementation. A better implementation would be an
-// asynchronous implementation and it is upto the graph provider to do that. This implementation
-// is very specific to tests being conducted here.
-class GrpcGraphServerImpl : public proto::GrpcGraphService::Service {
-private:
- std::string mServerAddress;
- std::unique_ptr<::grpc::Server> mServer;
- std::mutex mLock;
- std::condition_variable mShutdownCv;
- bool mShutdown = false;
-
-public:
- explicit GrpcGraphServerImpl(std::string address) : mServerAddress(address) {}
-
- virtual ~GrpcGraphServerImpl() {
- if (mServer) {
- mServer->Shutdown();
- std::unique_lock lock(mLock);
- if (!mShutdown) {
- mShutdownCv.wait_for(lock, std::chrono::seconds(10),
- [this]() { return mShutdown; });
- }
- }
- }
-
- void startServer() {
- if (mServer == nullptr) {
- ::grpc::ServerBuilder builder;
- builder.RegisterService(this);
- builder.AddListeningPort(mServerAddress, ::grpc::InsecureServerCredentials());
- mServer = builder.BuildAndStart();
- mServer->Wait();
- std::lock_guard lock(mLock);
- mShutdown = true;
- mShutdownCv.notify_one();
- }
- }
-
- ::grpc::Status GetGraphOptions(::grpc::ServerContext* context,
- const proto::GraphOptionsRequest* request,
- proto::GraphOptionsResponse* response) override {
- proto::Options options;
- options.set_graph_name(kGraphName);
- response->set_serialized_options(options.SerializeAsString());
- return ::grpc::Status::OK;
- }
-
- ::grpc::Status SetGraphConfig(::grpc::ServerContext* context,
- const proto::SetGraphConfigRequest* request,
- proto::StatusResponse* response) override {
- response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
- response->set_message(kSetGraphConfigMessage);
- return ::grpc::Status::OK;
- }
-
- ::grpc::Status SetDebugOption(::grpc::ServerContext* context,
- const proto::SetDebugRequest* request,
- proto::StatusResponse* response) override {
- response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
- response->set_message(kSetDebugOptionMessage);
- return ::grpc::Status::OK;
- }
-
- ::grpc::Status StartGraphExecution(::grpc::ServerContext* context,
- const proto::StartGraphExecutionRequest* request,
- proto::StatusResponse* response) override {
- response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
- response->set_message(kStartGraphMessage);
- return ::grpc::Status::OK;
- }
-
- ::grpc::Status ObserveOutputStream(
- ::grpc::ServerContext* context, const proto::ObserveOutputStreamRequest* request,
- ::grpc::ServerWriter<proto::OutputStreamResponse>* writer) override {
- // Write as many output packets as stream id. This is just to test different number of
- // packets received with each stream. Also write even numbered stream as a pixel packet
- // and odd numbered stream as a data packet.
- for (int i = 0; i < request->stream_id(); i++) {
- proto::OutputStreamResponse response;
- if (request->stream_id() % 2 == 0) {
- response.mutable_pixel_data()->set_data(kOutputStreamPacket);
- response.mutable_pixel_data()->set_height(1);
- response.mutable_pixel_data()->set_width(sizeof(kOutputStreamPacket));
- response.mutable_pixel_data()->set_step(sizeof(kOutputStreamPacket));
- response.mutable_pixel_data()->set_format(proto::PixelFormat::GRAY);
- EXPECT_TRUE(response.has_pixel_data());
- } else {
- response.set_semantic_data(kOutputStreamPacket);
- EXPECT_TRUE(response.has_semantic_data());
- }
- if (!writer->Write(response)) {
- return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost");
- }
- }
-
- return ::grpc::Status::OK;
- }
-
- ::grpc::Status StopGraphExecution(::grpc::ServerContext* context,
- const proto::StopGraphExecutionRequest* request,
- proto::StatusResponse* response) override {
- response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
- response->set_message(kStopGraphMessage);
- return ::grpc::Status::OK;
- }
-
- ::grpc::Status ResetGraph(::grpc::ServerContext* context,
- const proto::ResetGraphRequest* request,
- proto::StatusResponse* response) override {
- response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
- response->set_message(kResetGraphMessage);
- return ::grpc::Status::OK;
- }
-
- ::grpc::Status GetProfilingData(::grpc::ServerContext* context,
- const proto::ProfilingDataRequest* request,
- proto::ProfilingDataResponse* response) {
- response->set_data(kSetGraphConfigMessage);
- return ::grpc::Status::OK;
- }
-};
-
-class PrebuiltEngineInterfaceImpl : public PrebuiltEngineInterface {
-private:
- std::map<int, int> mNumPacketsPerStream;
- std::mutex mLock;
- std::condition_variable mCv;
- bool mGraphTerminated = false;
-
-public:
- // Prebuilt to engine interface
- void DispatchPixelData(int streamId, int64_t timestamp,
- const runner::InputFrame& frame) override {
- ASSERT_EQ(streamId % 2, 0);
- std::lock_guard lock(mLock);
- if (mNumPacketsPerStream.find(streamId) == mNumPacketsPerStream.end()) {
- mNumPacketsPerStream[streamId] = 1;
- } else {
- mNumPacketsPerStream[streamId]++;
- }
- }
-
- void DispatchSerializedData(int streamId, int64_t timestamp, std::string&& data) override {
- ASSERT_EQ(streamId % 2, 1);
- std::lock_guard lock(mLock);
- if (mNumPacketsPerStream.find(streamId) == mNumPacketsPerStream.end()) {
- mNumPacketsPerStream[streamId] = 1;
- } else {
- mNumPacketsPerStream[streamId]++;
- }
- }
-
- void DispatchGraphTerminationMessage(Status status, std::string&& msg) override {
- std::lock_guard lock(mLock);
- mGraphTerminated = true;
- mCv.notify_one();
- }
-
- bool waitForTermination() {
- std::unique_lock lock(mLock);
- if (!mGraphTerminated) {
- mCv.wait_for(lock, std::chrono::seconds(10), [this] { return mGraphTerminated; });
- }
- return mGraphTerminated;
- }
-
- int numPacketsForStream(int streamId) {
- std::lock_guard lock(mLock);
- auto it = mNumPacketsPerStream.find(streamId);
- if (it == mNumPacketsPerStream.end()) {
- return 0;
- }
- return it->second;
- }
-};
-
class GrpcGraphTest : public ::testing::Test {
private:
std::unique_ptr<GrpcGraphServerImpl> mServer;
diff --git a/cpp/computepipe/tests/runner/graph/LocalPrebuiltGraphTest.cpp b/cpp/computepipe/tests/runner/graph/LocalPrebuiltGraphTest.cpp
index d63ec51..ddc3aee 100644
--- a/cpp/computepipe/tests/runner/graph/LocalPrebuiltGraphTest.cpp
+++ b/cpp/computepipe/tests/runner/graph/LocalPrebuiltGraphTest.cpp
@@ -18,6 +18,7 @@
#include "ClientConfig.pb.h"
#include "LocalPrebuiltGraph.h"
#include "PrebuiltEngineInterface.h"
+#include "PrebuiltEngineInterfaceImpl.h"
#include "ProfilingType.pb.h"
#include "RunnerComponent.h"
#include "gmock/gmock-matchers.h"
@@ -36,44 +37,6 @@
namespace graph {
namespace {
-// Barebones implementation of the PrebuiltEngineInterface. This implementation should suffice for
-// basic cases. More complicated use cases might need their own implementation of it.
-typedef std::function<void(int, int64_t, const runner::InputFrame&)> PixelCallback;
-typedef std::function<void(int, int64_t, std::string&&)> SerializedStreamCallback;
-typedef std::function<void(Status, std::string&&)> GraphTerminationCallback;
-class PrebuiltEngineInterfaceImpl : public PrebuiltEngineInterface {
-private:
- PixelCallback mPixelCallbackFn;
- SerializedStreamCallback mSerializedStreamCallbackFn;
- GraphTerminationCallback mGraphTerminationCallbackFn;
-
-public:
- virtual ~PrebuiltEngineInterfaceImpl() = default;
-
- void DispatchPixelData(int streamId, int64_t timestamp,
- const runner::InputFrame& frame) override {
- mPixelCallbackFn(streamId, timestamp, frame);
- }
-
- void DispatchSerializedData(int streamId, int64_t timestamp, std::string&& data) override {
- mSerializedStreamCallbackFn(streamId, timestamp, std::move(data));
- }
-
- void DispatchGraphTerminationMessage(Status status, std::string&& msg) override {
- mGraphTerminationCallbackFn(status, std::move(msg));
- }
-
- void SetPixelCallback(PixelCallback callback) { mPixelCallbackFn = callback; }
-
- void SetSerializedStreamCallback(SerializedStreamCallback callback) {
- mSerializedStreamCallbackFn = callback;
- }
-
- void SetGraphTerminationCallback(GraphTerminationCallback callback) {
- mGraphTerminationCallbackFn = callback;
- }
-};
-
// The stub graph implementation is a passthrough implementation that does not run
// any graph and returns success for all implementations. The only useful things that
// it does for the tests are
diff --git a/cpp/computepipe/tests/runner/graph/includes/GrpcGraphServerImpl.h b/cpp/computepipe/tests/runner/graph/includes/GrpcGraphServerImpl.h
new file mode 100644
index 0000000..a168728
--- /dev/null
+++ b/cpp/computepipe/tests/runner/graph/includes/GrpcGraphServerImpl.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_GRPCGRAPHSERVERIMPL_H_
+#define CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_GRPCGRAPHSERVERIMPL_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <thread>
+
+#include <android-base/logging.h>
+#include <grpc++/grpc++.h>
+
+#include "GrpcPrebuiltGraphService.grpc.pb.h"
+#include "GrpcPrebuiltGraphService.pb.h"
+#include "Options.pb.h"
+#include "PrebuiltEngineInterface.h"
+#include "PrebuiltGraph.h"
+#include "RunnerComponent.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "types/Status.h"
+
+namespace android {
+namespace automotive {
+namespace computepipe {
+namespace graph {
+
+constexpr char kGraphName[] = "Stub graph name";
+constexpr char kSetGraphConfigMessage[] = "Stub set config message";
+constexpr char kSetDebugOptionMessage[] = "Stub set debug option message";
+constexpr char kStartGraphMessage[] = "Stub start graph message";
+constexpr char kStopGraphMessage[] = "Stub stop graph message";
+constexpr char kOutputStreamPacket[] = "Stub output stream packet";
+constexpr char kResetGraphMessage[] = "ResetGraphMessage";
+
+// This is a barebones synchronous server implementation. A better implementation would be an
+// asynchronous implementation and it is upto the graph provider to do that. This implementation
+// is very specific to tests being conducted here.
+class GrpcGraphServerImpl : public proto::GrpcGraphService::Service {
+private:
+ std::string mServerAddress;
+ std::unique_ptr<::grpc::Server> mServer;
+ std::mutex mLock;
+ std::condition_variable mShutdownCv;
+ bool mShutdown = false;
+
+public:
+ explicit GrpcGraphServerImpl(std::string address) : mServerAddress(address) {}
+
+ virtual ~GrpcGraphServerImpl() {
+ if (mServer) {
+ mServer->Shutdown();
+ std::unique_lock lock(mLock);
+ if (!mShutdown) {
+ mShutdownCv.wait_for(lock, std::chrono::seconds(10),
+ [this]() { return mShutdown; });
+ }
+ }
+ }
+
+ void startServer() {
+ if (mServer == nullptr) {
+ ::grpc::ServerBuilder builder;
+ builder.RegisterService(this);
+ builder.AddListeningPort(mServerAddress, ::grpc::InsecureServerCredentials());
+ mServer = builder.BuildAndStart();
+ mServer->Wait();
+ std::lock_guard lock(mLock);
+ mShutdown = true;
+ mShutdownCv.notify_one();
+ }
+ }
+
+ ::grpc::Status GetGraphOptions(::grpc::ServerContext* context,
+ const proto::GraphOptionsRequest* request,
+ proto::GraphOptionsResponse* response) override {
+ proto::Options options;
+ options.set_graph_name(kGraphName);
+ response->set_serialized_options(options.SerializeAsString());
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status SetGraphConfig(::grpc::ServerContext* context,
+ const proto::SetGraphConfigRequest* request,
+ proto::StatusResponse* response) override {
+ response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
+ response->set_message(kSetGraphConfigMessage);
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status SetDebugOption(::grpc::ServerContext* context,
+ const proto::SetDebugRequest* request,
+ proto::StatusResponse* response) override {
+ response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
+ response->set_message(kSetDebugOptionMessage);
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status StartGraphExecution(::grpc::ServerContext* context,
+ const proto::StartGraphExecutionRequest* request,
+ proto::StatusResponse* response) override {
+ response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
+ response->set_message(kStartGraphMessage);
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status ObserveOutputStream(
+ ::grpc::ServerContext* context, const proto::ObserveOutputStreamRequest* request,
+ ::grpc::ServerWriter<proto::OutputStreamResponse>* writer) override {
+ // Write as many output packets as stream id. This is just to test different number of
+ // packets received with each stream. Also write even numbered stream as a pixel packet
+ // and odd numbered stream as a data packet.
+ for (int i = 0; i < request->stream_id(); i++) {
+ proto::OutputStreamResponse response;
+ if (request->stream_id() % 2 == 0) {
+ response.mutable_pixel_data()->set_data(kOutputStreamPacket);
+ response.mutable_pixel_data()->set_height(1);
+ response.mutable_pixel_data()->set_width(sizeof(kOutputStreamPacket));
+ response.mutable_pixel_data()->set_step(sizeof(kOutputStreamPacket));
+ response.mutable_pixel_data()->set_format(proto::PixelFormat::GRAY);
+ EXPECT_TRUE(response.has_pixel_data());
+ } else {
+ response.set_semantic_data(kOutputStreamPacket);
+ EXPECT_TRUE(response.has_semantic_data());
+ }
+ if (!writer->Write(response)) {
+ return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost");
+ }
+ }
+
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status StopGraphExecution(::grpc::ServerContext* context,
+ const proto::StopGraphExecutionRequest* request,
+ proto::StatusResponse* response) override {
+ response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
+ response->set_message(kStopGraphMessage);
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status ResetGraph(::grpc::ServerContext* context,
+ const proto::ResetGraphRequest* request,
+ proto::StatusResponse* response) override {
+ response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
+ response->set_message(kResetGraphMessage);
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status GetProfilingData(::grpc::ServerContext* context,
+ const proto::ProfilingDataRequest* request,
+ proto::ProfilingDataResponse* response) {
+ response->set_data(kSetGraphConfigMessage);
+ return ::grpc::Status::OK;
+ }
+};
+
+class PrebuiltEngineInterfaceImpl : public PrebuiltEngineInterface {
+private:
+ std::map<int, int> mNumPacketsPerStream;
+ std::mutex mLock;
+ std::condition_variable mCv;
+ bool mGraphTerminated = false;
+
+public:
+ // Prebuilt to engine interface
+ void DispatchPixelData(int streamId, int64_t timestamp,
+ const runner::InputFrame& frame) override {
+ ASSERT_EQ(streamId % 2, 0);
+ std::lock_guard lock(mLock);
+ if (mNumPacketsPerStream.find(streamId) == mNumPacketsPerStream.end()) {
+ mNumPacketsPerStream[streamId] = 1;
+ } else {
+ mNumPacketsPerStream[streamId]++;
+ }
+ }
+
+ void DispatchSerializedData(int streamId, int64_t timestamp, std::string&& data) override {
+ ASSERT_EQ(streamId % 2, 1);
+ std::lock_guard lock(mLock);
+ if (mNumPacketsPerStream.find(streamId) == mNumPacketsPerStream.end()) {
+ mNumPacketsPerStream[streamId] = 1;
+ } else {
+ mNumPacketsPerStream[streamId]++;
+ }
+ }
+
+ void DispatchGraphTerminationMessage(Status status, std::string&& msg) override {
+ std::lock_guard lock(mLock);
+ mGraphTerminated = true;
+ mCv.notify_one();
+ }
+
+ bool waitForTermination() {
+ std::unique_lock lock(mLock);
+ if (!mGraphTerminated) {
+ mCv.wait_for(lock, std::chrono::seconds(10), [this] { return mGraphTerminated; });
+ }
+ return mGraphTerminated;
+ }
+
+ int numPacketsForStream(int streamId) {
+ std::lock_guard lock(mLock);
+ auto it = mNumPacketsPerStream.find(streamId);
+ if (it == mNumPacketsPerStream.end()) {
+ return 0;
+ }
+ return it->second;
+ }
+};
+
+} // namespace graph
+} // namespace computepipe
+} // namespace automotive
+} // namespace android
+
+#endif // CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_GRPCGRAPHSERVERIMPL_H_
diff --git a/cpp/computepipe/tests/runner/graph/includes/PrebuiltEngineInterfaceImpl.h b/cpp/computepipe/tests/runner/graph/includes/PrebuiltEngineInterfaceImpl.h
new file mode 100644
index 0000000..70326ab
--- /dev/null
+++ b/cpp/computepipe/tests/runner/graph/includes/PrebuiltEngineInterfaceImpl.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_PREBUILTENGINEINTERFACEIMPL_H_
+#define CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_PREBUILTENGINEINTERFACEIMPL_H_
+
+#include <string>
+
+#include "ClientConfig.pb.h"
+#include "LocalPrebuiltGraph.h"
+#include "PrebuiltEngineInterface.h"
+#include "ProfilingType.pb.h"
+#include "RunnerComponent.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "types/Status.h"
+
+namespace android {
+namespace automotive {
+namespace computepipe {
+namespace graph {
+
+// Barebones implementation of the PrebuiltEngineInterface. This implementation should suffice for
+// basic cases. More complicated use cases might need their own implementation of it.
+typedef std::function<void(int, int64_t, const runner::InputFrame&)> PixelCallback;
+typedef std::function<void(int, int64_t, std::string&&)> SerializedStreamCallback;
+typedef std::function<void(Status, std::string&&)> GraphTerminationCallback;
+class PrebuiltEngineInterfaceImpl : public PrebuiltEngineInterface {
+private:
+ PixelCallback mPixelCallbackFn;
+ SerializedStreamCallback mSerializedStreamCallbackFn;
+ GraphTerminationCallback mGraphTerminationCallbackFn;
+
+public:
+ virtual ~PrebuiltEngineInterfaceImpl() = default;
+
+ void DispatchPixelData(int streamId, int64_t timestamp,
+ const runner::InputFrame& frame) override {
+ mPixelCallbackFn(streamId, timestamp, frame);
+ }
+
+ void DispatchSerializedData(int streamId, int64_t timestamp, std::string&& data) override {
+ mSerializedStreamCallbackFn(streamId, timestamp, std::move(data));
+ }
+
+ void DispatchGraphTerminationMessage(Status status, std::string&& msg) override {
+ mGraphTerminationCallbackFn(status, std::move(msg));
+ }
+
+ void SetPixelCallback(PixelCallback callback) { mPixelCallbackFn = callback; }
+
+ void SetSerializedStreamCallback(SerializedStreamCallback callback) {
+ mSerializedStreamCallbackFn = callback;
+ }
+
+ void SetGraphTerminationCallback(GraphTerminationCallback callback) {
+ mGraphTerminationCallbackFn = callback;
+ }
+};
+
+} // namespace graph
+} // namespace computepipe
+} // namespace automotive
+} // namespace android
+
+#endif // CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_PREBUILTENGINEINTERFACEIMPL_H_
diff --git a/cpp/powerpolicy/Android.bp b/cpp/powerpolicy/Android.bp
new file mode 100644
index 0000000..3c92933
--- /dev/null
+++ b/cpp/powerpolicy/Android.bp
@@ -0,0 +1,56 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+ name: "carpowerpolicyserver_defaults",
+ cflags: [
+ "-Wall",
+ "-Wno-missing-field-initializers",
+ "-Werror",
+ "-Wno-unused-variable",
+ "-Wunused-parameter",
+ ],
+ shared_libs: [
+ "carpowerpolicy_aidl_interface-cpp",
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+}
+
+cc_library {
+ name: "libcarpowerpolicy_server",
+ srcs: [
+ "src/CarPowerPolicyServer.cpp",
+ ],
+ defaults: [
+ "carpowerpolicyserver_defaults",
+ ],
+}
+
+cc_binary {
+ name: "carpowerpolicyd",
+ defaults: [
+ "carpowerpolicyserver_defaults",
+ ],
+ srcs: [
+ "src/main.cpp",
+ ],
+ init_rc: ["carpowerpolicyd.rc"],
+ shared_libs: [
+ "libcarpowerpolicy_server",
+ ],
+ vintf_fragments: ["carpowerpolicyd.xml"],
+}
diff --git a/cpp/powerpolicy/carpowerpolicyd.rc b/cpp/powerpolicy/carpowerpolicyd.rc
new file mode 100644
index 0000000..b5726a9
--- /dev/null
+++ b/cpp/powerpolicy/carpowerpolicyd.rc
@@ -0,0 +1,18 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+service carpowerpolicyd /system/bin/carpowerpolicyd
+ class hal
+ user system
+ disabled
diff --git a/cpp/powerpolicy/carpowerpolicyd.xml b/cpp/powerpolicy/carpowerpolicyd.xml
new file mode 100644
index 0000000..e8df893
--- /dev/null
+++ b/cpp/powerpolicy/carpowerpolicyd.xml
@@ -0,0 +1,24 @@
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest version="1.0" type="framework">
+ <hal format="aidl">
+ <name>android.frameworks.automotive.powerpolicy</name>
+ <interface>
+ <name>ICarPowerPolicyServer</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/cpp/powerpolicy/src/CarPowerPolicyServer.cpp b/cpp/powerpolicy/src/CarPowerPolicyServer.cpp
new file mode 100644
index 0000000..a6fc476
--- /dev/null
+++ b/cpp/powerpolicy/src/CarPowerPolicyServer.cpp
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "powerpolicydaemon"
+
+#include "CarPowerPolicyServer.h"
+
+namespace android {
+namespace frameworks {
+namespace automotive {
+namespace powerpolicy {
+
+using android::base::Error;
+using android::base::Result;
+using android::binder::Status;
+
+sp<CarPowerPolicyServer> CarPowerPolicyServer::sCarPowerPolicyServer = nullptr;
+
+Result<void> CarPowerPolicyServer::startService(const android::sp<Looper>& looper) {
+ if (sCarPowerPolicyServer != nullptr) {
+ return Error(INVALID_OPERATION) << "Cannot start service more than once";
+ }
+ sp<CarPowerPolicyServer> server = new CarPowerPolicyServer();
+ const auto& ret = server->init(looper);
+ if (!ret.ok()) {
+ return Error(ret.error().code())
+ << "Failed to start car power policy server: " << ret.error();
+ }
+ return {};
+}
+
+void CarPowerPolicyServer::terminateService() {
+ if (sCarPowerPolicyServer != nullptr) {
+ sCarPowerPolicyServer->terminate();
+ sCarPowerPolicyServer = nullptr;
+ }
+}
+
+Status CarPowerPolicyServer::getCurrentPowerPolicy(CarPowerPolicy* /*aidlReturn*/) {
+ return Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION, "Not implemented");
+}
+
+Status CarPowerPolicyServer::getPowerComponentState(PowerComponent /*componentId*/,
+ bool* /*aidlReturn*/) {
+ return Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION, "Not implemented");
+}
+
+Status CarPowerPolicyServer::registerPowerPolicyChangeCallback(
+ const sp<ICarPowerPolicyChangeCallback>& /*callback*/,
+ const CarPowerPolicyFilter& /*filter*/) {
+ return Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION, "Not implemented");
+}
+
+Status CarPowerPolicyServer::unregisterPowerPolicyChangeCallback(
+ const sp<ICarPowerPolicyChangeCallback>& /*callback*/) {
+ return Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION, "Not implemented");
+}
+
+status_t CarPowerPolicyServer::dump(int /*fd*/, const Vector<String16>& /*args*/) {
+ // TODO(b/162599168): implement here
+ return UNKNOWN_ERROR;
+}
+
+Result<void> CarPowerPolicyServer::init(const sp<Looper>& /*looper*/) {
+ return Error(-1) << "Not implemented";
+}
+
+void CarPowerPolicyServer::terminate() {
+ // TODO(b/162599168): implement here
+}
+
+void CarPowerPolicyServer::binderDied(const wp<IBinder>& /*who*/) {
+ // TODO(b/162599168): implement here
+}
+
+} // namespace powerpolicy
+} // namespace automotive
+} // namespace frameworks
+} // namespace android
diff --git a/cpp/powerpolicy/src/CarPowerPolicyServer.h b/cpp/powerpolicy/src/CarPowerPolicyServer.h
new file mode 100644
index 0000000..c6bf22b
--- /dev/null
+++ b/cpp/powerpolicy/src/CarPowerPolicyServer.h
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CPP_POWERPOLICY_SRC_CARPOWERPOLICYSERVER_H_
+#define CPP_POWERPOLICY_SRC_CARPOWERPOLICYSERVER_H_
+
+#include <android-base/result.h>
+#include <android/frameworks/automotive/powerpolicy/BnCarPowerPolicyServer.h>
+#include <binder/IBinder.h>
+#include <binder/Status.h>
+#include <utils/Looper.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace frameworks {
+namespace automotive {
+namespace powerpolicy {
+
+class CarPowerPolicyServer : public BnCarPowerPolicyServer, public IBinder::DeathRecipient {
+public:
+ static android::base::Result<void> startService(const android::sp<Looper>& looper);
+ static void terminateService();
+
+ status_t dump(int fd, const Vector<String16>& args) override;
+ binder::Status getCurrentPowerPolicy(CarPowerPolicy* aidlReturn) override;
+ binder::Status getPowerComponentState(PowerComponent componentId, bool* aidlReturn) override;
+ binder::Status registerPowerPolicyChangeCallback(
+ const sp<ICarPowerPolicyChangeCallback>& callback,
+ const CarPowerPolicyFilter& filter) override;
+ binder::Status unregisterPowerPolicyChangeCallback(
+ const sp<ICarPowerPolicyChangeCallback>& callback) override;
+ void binderDied(const wp<IBinder>& who) override;
+
+ base::Result<void> init(const sp<Looper>& looper);
+ void terminate();
+
+private:
+ static sp<CarPowerPolicyServer> sCarPowerPolicyServer;
+
+ sp<Looper> mHandlerLooper;
+};
+
+} // namespace powerpolicy
+} // namespace automotive
+} // namespace frameworks
+} // namespace android
+
+#endif // CPP_POWERPOLICY_SRC_CARPOWERPOLICYSERVER_H_
diff --git a/cpp/powerpolicy/src/main.cpp b/cpp/powerpolicy/src/main.cpp
new file mode 100644
index 0000000..5288c5c
--- /dev/null
+++ b/cpp/powerpolicy/src/main.cpp
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "powerpolicydaemon"
+
+#include "CarPowerPolicyServer.h"
+
+#include <android-base/result.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <log/log.h>
+#include <signal.h>
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+
+using android::IPCThreadState;
+using android::Looper;
+using android::ProcessState;
+using android::sp;
+using android::frameworks::automotive::powerpolicy::CarPowerPolicyServer;
+
+namespace {
+
+const size_t kMaxBinderThreadCount = 2;
+
+void sigHandler(int sig) {
+ IPCThreadState::self()->stopProcess();
+ CarPowerPolicyServer::terminateService();
+ ALOGW("powerpolicy daemon terminated on receiving signal %d.", sig);
+ exit(1);
+}
+
+void registerSigHandler() {
+ struct sigaction sa;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = sigHandler;
+ sigaction(SIGQUIT, &sa, nullptr);
+ sigaction(SIGTERM, &sa, nullptr);
+}
+
+} // namespace
+
+int main(int /*argc*/, char** /*argv*/) {
+ registerSigHandler();
+
+ // Set up the binder
+ sp<ProcessState> ps(ProcessState::self());
+ ps->setThreadPoolMaxThreadCount(kMaxBinderThreadCount);
+ ps->startThreadPool();
+ ps->giveThreadPoolName();
+ IPCThreadState::self()->disableBackgroundScheduling(true);
+
+ // Set up the looper
+ sp<Looper> looper(Looper::prepare(/*opts=*/0));
+
+ // Start the services
+ auto result = CarPowerPolicyServer::startService(looper);
+ if (!result.ok()) {
+ ALOGE("Failed to start service: %s", result.error().message().c_str());
+ CarPowerPolicyServer::terminateService();
+ exit(result.error().code());
+ }
+
+ while (true) {
+ looper->pollAll(/*timeoutMillis=*/-1);
+ }
+ ALOGW("Car power policy server escaped from its loop.");
+
+ return 0;
+}