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;
+}