Merge "Added changes to use seperate payload for DTMF tx and rx" into main-ims-dev
diff --git a/automotive/remoteaccess/impl/default/client/Android.bp b/automotive/remoteaccess/hal/default/Android.bp
similarity index 88%
rename from automotive/remoteaccess/impl/default/client/Android.bp
rename to automotive/remoteaccess/hal/default/Android.bp
index 6327637..51be330 100644
--- a/automotive/remoteaccess/impl/default/client/Android.bp
+++ b/automotive/remoteaccess/hal/default/Android.bp
@@ -29,14 +29,19 @@
"RemoteAccessService",
],
shared_libs: [
+ "libbase",
"libbinder_ndk",
"liblog",
"libutils",
"libgrpc++",
"libprotobuf-cpp-full",
],
+ defaults: [
+ "vhalclient_defaults",
+ ],
cflags: [
"-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
],
}
@@ -51,10 +56,15 @@
whole_static_libs: [
"android.hardware.automotive.remoteaccess-V1-ndk",
"wakeup_client_protos",
+ "libvhalclient",
+ ],
+ defaults: [
+ "vhalclient_defaults",
],
shared_libs: [
"libbase",
"libbinder_ndk",
+ "libcutils",
"liblog",
"libutils",
"libgrpc++",
diff --git a/automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
similarity index 71%
rename from automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h
rename to automotive/remoteaccess/hal/default/include/RemoteAccessService.h
index 806440a..74c2af4 100644
--- a/automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h
+++ b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
@@ -16,10 +16,14 @@
#pragma once
+#include <IVhalClient.h>
#include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteAccess.h>
+#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
#include <aidl/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.h>
#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+#include <utils/SystemClock.h>
#include <wakeup_client.grpc.pb.h>
#include <string>
@@ -30,6 +34,27 @@
namespace automotive {
namespace remoteaccess {
+// A IRemoteTaskCallback implementation for debug purpose.
+class DebugRemoteTaskCallback final
+ : public aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback {
+ public:
+ DebugRemoteTaskCallback() { mStartTimeMillis = android::uptimeMillis(); };
+
+ ndk::ScopedAStatus onRemoteTaskRequested(const std::string& clientId,
+ const std::vector<uint8_t>& data) override;
+ std::string printTasks();
+
+ private:
+ struct TaskData {
+ std::string clientId;
+ std::vector<uint8_t> data;
+ };
+
+ std::mutex mLock;
+ int64_t mStartTimeMillis;
+ std::vector<TaskData> mTasks;
+};
+
class RemoteAccessService
: public aidl::android::hardware::automotive::remoteaccess::BnRemoteAccess {
public:
@@ -51,10 +76,14 @@
ndk::ScopedAStatus notifyApStateChange(
const aidl::android::hardware::automotive::remoteaccess::ApState& newState) override;
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
private:
// For testing.
friend class RemoteAccessServiceUnitTest;
+ static bool checkDumpPermission();
+
WakeupClient::StubInterface* mGrpcStub;
std::thread mThread;
std::mutex mLock;
@@ -69,12 +98,16 @@
bool mTaskLoopRunning GUARDED_BY(mStartStopTaskLoopLock);
// Default wait time before retry connecting to remote access client is 10s.
size_t mRetryWaitInMs = 10'000;
+ std::shared_ptr<DebugRemoteTaskCallback> mDebugCallback;
void runTaskLoop();
void maybeStartTaskLoop();
void maybeStopTaskLoop();
+ ndk::ScopedAStatus getDeviceIdWithClient(
+ android::frameworks::automotive::vhal::IVhalClient& client, std::string* deviceId);
void setRetryWaitInMs(size_t retryWaitInMs) { mRetryWaitInMs = retryWaitInMs; }
+ void dumpHelp(int fd);
};
} // namespace remoteaccess
diff --git a/automotive/remoteaccess/impl/default/proto/Android.bp b/automotive/remoteaccess/hal/default/proto/Android.bp
similarity index 100%
rename from automotive/remoteaccess/impl/default/proto/Android.bp
rename to automotive/remoteaccess/hal/default/proto/Android.bp
diff --git a/automotive/remoteaccess/impl/default/proto/wakeup_client.proto b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
similarity index 100%
rename from automotive/remoteaccess/impl/default/proto/wakeup_client.proto
rename to automotive/remoteaccess/hal/default/proto/wakeup_client.proto
diff --git a/automotive/remoteaccess/impl/default/client/remoteaccess-default-service.rc b/automotive/remoteaccess/hal/default/remoteaccess-default-service.rc
similarity index 100%
rename from automotive/remoteaccess/impl/default/client/remoteaccess-default-service.rc
rename to automotive/remoteaccess/hal/default/remoteaccess-default-service.rc
diff --git a/automotive/remoteaccess/impl/default/client/remoteaccess-default-service.xml b/automotive/remoteaccess/hal/default/remoteaccess-default-service.xml
similarity index 100%
rename from automotive/remoteaccess/impl/default/client/remoteaccess-default-service.xml
rename to automotive/remoteaccess/hal/default/remoteaccess-default-service.xml
diff --git a/automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
similarity index 70%
rename from automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp
rename to automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
index 7431898..8720c2f 100644
--- a/automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
@@ -20,27 +20,35 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <grpcpp/create_channel.h>
+#include <stdlib.h>
#include <utils/Log.h>
+constexpr char SERVICE_NAME[] = "android.hardware.automotive.remoteaccess.IRemoteAccess/default";
+
int main(int /* argc */, char* /* argv */[]) {
ALOGI("Registering RemoteAccessService as service...");
- // TODO(b/241483300): Create GrpcClientStub here.
+#ifndef GRPC_SERVICE_ADDRESS
+ ALOGE("GRPC_SERVICE_ADDRESS is not defined, exiting");
+ exit(1);
+#endif
+ auto channel = grpc::CreateChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials());
+ auto clientStub = android::hardware::automotive::remoteaccess::WakeupClient::NewStub(channel);
auto service = ndk::SharedRefBase::make<
- android::hardware::automotive::remoteaccess::RemoteAccessService>(nullptr);
+ android::hardware::automotive::remoteaccess::RemoteAccessService>(clientStub.get());
- binder_exception_t err = AServiceManager_addService(
- service->asBinder().get(), "android.hardware.automotive.remote.IRemoteAccess/default");
+ binder_exception_t err = AServiceManager_addService(service->asBinder().get(), SERVICE_NAME);
if (err != EX_NONE) {
ALOGE("failed to register android.hardware.automotive.remote.IRemoteAccess service, "
"exception: %d",
err);
- return 1;
+ exit(1);
}
if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
ALOGE("%s", "failed to set thread pool max thread count");
- return 1;
+ exit(1);
}
ABinderProcess_startThreadPool();
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
new file mode 100644
index 0000000..72f37d7
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2022 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 "RemoteAccessService.h"
+
+#include <VehicleUtils.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_status.h>
+#include <grpc++/grpc++.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Log.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::remoteaccess::ApState;
+using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::android::base::ScopedLockAssertion;
+using ::android::base::StringAppendF;
+using ::android::base::StringPrintf;
+using ::android::frameworks::automotive::vhal::IVhalClient;
+using ::android::hardware::automotive::vehicle::toInt;
+using ::grpc::ClientContext;
+using ::grpc::ClientReaderInterface;
+using ::grpc::Status;
+using ::grpc::StatusCode;
+using ::ndk::ScopedAStatus;
+
+const std::string WAKEUP_SERVICE_NAME = "com.google.vehicle.wakeup";
+constexpr char COMMAND_SET_AP_STATE[] = "--set-ap-state";
+constexpr char COMMAND_START_DEBUG_CALLBACK[] = "--start-debug-callback";
+constexpr char COMMAND_STOP_DEBUG_CALLBACK[] = "--stop-debug-callback";
+constexpr char COMMAND_SHOW_TASK[] = "--show-task";
+constexpr char COMMAND_GET_DEVICE_ID[] = "--get-device-id";
+
+std::vector<uint8_t> stringToBytes(const std::string& s) {
+ const char* data = s.data();
+ return std::vector<uint8_t>(data, data + s.size());
+}
+
+ScopedAStatus rpcStatusToScopedAStatus(const Status& status, const std::string& errorMsg) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ status.error_code(), (errorMsg + ", error: " + status.error_message()).c_str());
+}
+
+std::string printBytes(const std::vector<uint8_t>& bytes) {
+ std::string s;
+ for (size_t i = 0; i < bytes.size(); i++) {
+ StringAppendF(&s, "%02x", bytes[i]);
+ }
+ return s;
+}
+
+bool checkBoolFlag(const char* flag) {
+ return !strcmp(flag, "1") || !strcmp(flag, "0");
+}
+
+void dprintErrorStatus(int fd, const char* detail, const ScopedAStatus& status) {
+ dprintf(fd, "%s, code: %d, error: %s\n", detail, status.getStatus(), status.getMessage());
+}
+
+} // namespace
+
+RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub)
+ : mGrpcStub(grpcStub){};
+
+RemoteAccessService::~RemoteAccessService() {
+ maybeStopTaskLoop();
+}
+
+void RemoteAccessService::maybeStartTaskLoop() {
+ std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
+ if (mTaskLoopRunning) {
+ return;
+ }
+
+ mThread = std::thread([this]() { runTaskLoop(); });
+
+ mTaskLoopRunning = true;
+}
+
+void RemoteAccessService::maybeStopTaskLoop() {
+ std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
+ if (!mTaskLoopRunning) {
+ return;
+ }
+
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ // Try to stop the reading stream.
+ if (mGetRemoteTasksContext) {
+ mGetRemoteTasksContext->TryCancel();
+ mGetRemoteTasksContext.reset();
+ }
+ mTaskWaitStopped = true;
+ mCv.notify_all();
+ }
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+
+ mTaskLoopRunning = false;
+}
+
+void RemoteAccessService::runTaskLoop() {
+ GetRemoteTasksRequest request = {};
+ std::unique_ptr<ClientReaderInterface<GetRemoteTasksResponse>> reader;
+ while (true) {
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mGetRemoteTasksContext.reset(new ClientContext());
+ reader = mGrpcStub->GetRemoteTasks(mGetRemoteTasksContext.get(), request);
+ }
+ GetRemoteTasksResponse response;
+ while (reader->Read(&response)) {
+ ALOGI("Receiving one task from remote task client");
+
+ std::shared_ptr<IRemoteTaskCallback> callback;
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ callback = mRemoteTaskCallback;
+ }
+ if (callback == nullptr) {
+ ALOGD("No callback registered, task ignored");
+ continue;
+ }
+ ALOGD("Calling onRemoteTaskRequested callback for client ID: %s",
+ response.clientid().c_str());
+ ScopedAStatus callbackStatus = callback->onRemoteTaskRequested(
+ response.clientid(), stringToBytes(response.data()));
+ if (!callbackStatus.isOk()) {
+ ALOGE("Failed to call onRemoteTaskRequested callback, status: %d, message: %s",
+ callbackStatus.getStatus(), callbackStatus.getMessage());
+ }
+ }
+ Status status = reader->Finish();
+
+ ALOGE("GetRemoteTasks stream breaks, code: %d, message: %s, sleeping for 10s and retry",
+ status.error_code(), status.error_message().c_str());
+ // The long lasting connection should not return. But if the server returns, retry after
+ // 10s.
+ {
+ std::unique_lock lk(mLock);
+ if (mCv.wait_for(lk, std::chrono::milliseconds(mRetryWaitInMs), [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mTaskWaitStopped;
+ })) {
+ // If the stopped flag is set, we are quitting, exit the loop.
+ break;
+ }
+ }
+ }
+}
+
+ScopedAStatus RemoteAccessService::getDeviceId(std::string* deviceId) {
+ auto vhalClient = IVhalClient::tryCreate();
+ if (vhalClient == nullptr) {
+ ALOGE("Failed to connect to VHAL");
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ /*errorCode=*/0, "Failed to connect to VHAL to get device ID");
+ }
+ return getDeviceIdWithClient(*vhalClient.get(), deviceId);
+}
+
+ScopedAStatus RemoteAccessService::getDeviceIdWithClient(IVhalClient& vhalClient,
+ std::string* deviceId) {
+ auto result = vhalClient.getValueSync(
+ *vhalClient.createHalPropValue(toInt(VehicleProperty::INFO_VIN)));
+ if (!result.ok()) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ /*errorCode=*/0,
+ ("failed to get INFO_VIN from VHAL: " + result.error().message()).c_str());
+ }
+ *deviceId = (*result)->getStringValue();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::getWakeupServiceName(std::string* wakeupServiceName) {
+ *wakeupServiceName = WAKEUP_SERVICE_NAME;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::setRemoteTaskCallback(
+ const std::shared_ptr<IRemoteTaskCallback>& callback) {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mRemoteTaskCallback = callback;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::clearRemoteTaskCallback() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mRemoteTaskCallback.reset();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState) {
+ ClientContext context;
+ NotifyWakeupRequiredRequest request = {};
+ request.set_iswakeuprequired(newState.isWakeupRequired);
+ NotifyWakeupRequiredResponse response = {};
+ Status status = mGrpcStub->NotifyWakeupRequired(&context, request, &response);
+ if (!status.ok()) {
+ return rpcStatusToScopedAStatus(status, "Failed to notify isWakeupRequired");
+ }
+
+ if (newState.isReadyForRemoteTask) {
+ maybeStartTaskLoop();
+ } else {
+ maybeStopTaskLoop();
+ }
+ return ScopedAStatus::ok();
+}
+
+bool RemoteAccessService::checkDumpPermission() {
+ uid_t uid = AIBinder_getCallingUid();
+ return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
+}
+
+void RemoteAccessService::dumpHelp(int fd) {
+ dprintf(fd, "%s",
+ (std::string("RemoteAccess HAL debug interface, Usage: \n") + COMMAND_SET_AP_STATE +
+ " [0/1](isReadyForRemoteTask) [0/1](isWakeupRequired) Set the new AP state\n" +
+ COMMAND_START_DEBUG_CALLBACK +
+ " Start a debug callback that will record the received tasks\n" +
+ COMMAND_STOP_DEBUG_CALLBACK + " Stop the debug callback\n" + COMMAND_SHOW_TASK +
+ " Show tasks received by debug callback\n" + COMMAND_GET_DEVICE_ID +
+ " Get device id\n")
+ .c_str());
+}
+
+binder_status_t RemoteAccessService::dump(int fd, const char** args, uint32_t numArgs) {
+ if (!checkDumpPermission()) {
+ dprintf(fd, "Caller must be root, system or shell\n");
+ return STATUS_PERMISSION_DENIED;
+ }
+
+ if (numArgs == 0) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+
+ if (!strcmp(args[0], COMMAND_SET_AP_STATE)) {
+ if (numArgs < 3) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ ApState apState = {};
+ const char* remoteTaskFlag = args[1];
+ if (!strcmp(remoteTaskFlag, "1") && !strcmp(remoteTaskFlag, "0")) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!checkBoolFlag(args[1])) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!strcmp(args[1], "1")) {
+ apState.isReadyForRemoteTask = true;
+ }
+ if (!checkBoolFlag(args[2])) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!strcmp(args[2], "1")) {
+ apState.isWakeupRequired = true;
+ }
+ auto status = notifyApStateChange(apState);
+ if (!status.isOk()) {
+ dprintErrorStatus(fd, "Failed to set AP state", status);
+ } else {
+ dprintf(fd, "successfully set the new AP state\n");
+ }
+ } else if (!strcmp(args[0], COMMAND_START_DEBUG_CALLBACK)) {
+ mDebugCallback = ndk::SharedRefBase::make<DebugRemoteTaskCallback>();
+ setRemoteTaskCallback(mDebugCallback);
+ dprintf(fd, "Debug callback registered\n");
+ } else if (!strcmp(args[0], COMMAND_STOP_DEBUG_CALLBACK)) {
+ if (mDebugCallback) {
+ mDebugCallback.reset();
+ }
+ clearRemoteTaskCallback();
+ dprintf(fd, "Debug callback unregistered\n");
+ } else if (!strcmp(args[0], COMMAND_SHOW_TASK)) {
+ if (mDebugCallback) {
+ dprintf(fd, "%s", mDebugCallback->printTasks().c_str());
+ } else {
+ dprintf(fd, "Debug callback is not currently used, use \"%s\" first.\n",
+ COMMAND_START_DEBUG_CALLBACK);
+ }
+ } else if (!strcmp(args[0], COMMAND_GET_DEVICE_ID)) {
+ std::string deviceId;
+ auto status = getDeviceId(&deviceId);
+ if (!status.isOk()) {
+ dprintErrorStatus(fd, "Failed to get device ID", status);
+ } else {
+ dprintf(fd, "Device Id: %s\n", deviceId.c_str());
+ }
+ } else {
+ dumpHelp(fd);
+ }
+
+ return STATUS_OK;
+}
+
+ScopedAStatus DebugRemoteTaskCallback::onRemoteTaskRequested(const std::string& clientId,
+ const std::vector<uint8_t>& data) {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mTasks.push_back({
+ .clientId = clientId,
+ .data = data,
+ });
+ return ScopedAStatus::ok();
+}
+
+std::string DebugRemoteTaskCallback::printTasks() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ std::string s = StringPrintf("Received %zu tasks in %f seconds", mTasks.size(),
+ (android::uptimeMillis() - mStartTimeMillis) / 1000.);
+ for (size_t i = 0; i < mTasks.size(); i++) {
+ StringAppendF(&s, "Client Id: %s, Data: %s\n", mTasks[i].clientId.c_str(),
+ printBytes(mTasks[i].data).c_str());
+ }
+ return s;
+}
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/impl/default/test/Android.bp b/automotive/remoteaccess/hal/default/test/Android.bp
similarity index 94%
rename from automotive/remoteaccess/impl/default/test/Android.bp
rename to automotive/remoteaccess/hal/default/test/Android.bp
index e92440f..227175a 100644
--- a/automotive/remoteaccess/impl/default/test/Android.bp
+++ b/automotive/remoteaccess/hal/default/test/Android.bp
@@ -24,6 +24,7 @@
"RemoteAccessService",
],
shared_libs: [
+ "libbase",
"libbinder_ndk",
"liblog",
"libutils",
@@ -36,6 +37,9 @@
"libgtest",
"libgmock",
],
+ defaults: [
+ "vhalclient_defaults",
+ ],
cflags: [
"-Wno-unused-parameter",
],
diff --git a/automotive/remoteaccess/impl/default/test/RemoteAccessServiceUnitTest.cpp b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
similarity index 78%
rename from automotive/remoteaccess/impl/default/test/RemoteAccessServiceUnitTest.cpp
rename to automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
index 11523f6..8c4fa08 100644
--- a/automotive/remoteaccess/impl/default/test/RemoteAccessServiceUnitTest.cpp
+++ b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
@@ -16,8 +16,11 @@
#include "RemoteAccessService.h"
+#include <AidlHalPropValue.h>
+#include <IVhalClient.h>
#include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropValue.h>
#include <gmock/gmock.h>
#include <grpcpp/test/mock_stream.h>
#include <gtest/gtest.h>
@@ -30,10 +33,20 @@
namespace automotive {
namespace remoteaccess {
+namespace {
+
using ::android::base::ScopedLockAssertion;
+using ::android::frameworks::automotive::vhal::AidlHalPropValue;
+using ::android::frameworks::automotive::vhal::IHalPropConfig;
+using ::android::frameworks::automotive::vhal::IHalPropValue;
+using ::android::frameworks::automotive::vhal::ISubscriptionCallback;
+using ::android::frameworks::automotive::vhal::ISubscriptionClient;
+using ::android::frameworks::automotive::vhal::IVhalClient;
+using ::android::frameworks::automotive::vhal::VhalClientResult;
using ::aidl::android::hardware::automotive::remoteaccess::ApState;
using ::aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::grpc::ClientAsyncReaderInterface;
using ::grpc::ClientAsyncResponseReaderInterface;
@@ -49,6 +62,10 @@
using ::testing::Return;
using ::testing::SetArgPointee;
+constexpr char kTestVin[] = "test_VIN";
+
+} // namespace
+
class MockGrpcClientStub : public WakeupClient::StubInterface {
public:
MOCK_METHOD(ClientReaderInterface<GetRemoteTasksResponse>*, GetRemoteTasksRaw,
@@ -73,6 +90,62 @@
CompletionQueue* cq));
};
+class FakeVhalClient final : public android::frameworks::automotive::vhal::IVhalClient {
+ public:
+ inline bool isAidlVhal() { return true; }
+
+ VhalClientResult<std::unique_ptr<IHalPropValue>> getValueSync(
+ const IHalPropValue& requestValue) override {
+ auto propValue = std::make_unique<AidlHalPropValue>(requestValue.getPropId());
+ propValue->setStringValue(kTestVin);
+ return propValue;
+ }
+
+ std::unique_ptr<IHalPropValue> createHalPropValue(int32_t propId) override {
+ return std::make_unique<AidlHalPropValue>(propId);
+ }
+
+ // Functions we do not care.
+ std::unique_ptr<IHalPropValue> createHalPropValue([[maybe_unused]] int32_t propId,
+ [[maybe_unused]] int32_t areaId) override {
+ return nullptr;
+ }
+
+ void getValue([[maybe_unused]] const IHalPropValue& requestValue,
+ [[maybe_unused]] std::shared_ptr<GetValueCallbackFunc> callback) override {}
+
+ void setValue([[maybe_unused]] const IHalPropValue& requestValue,
+ [[maybe_unused]] std::shared_ptr<SetValueCallbackFunc> callback) override {}
+
+ VhalClientResult<void> setValueSync([[maybe_unused]] const IHalPropValue& requestValue) {
+ return {};
+ }
+
+ VhalClientResult<void> addOnBinderDiedCallback(
+ [[maybe_unused]] std::shared_ptr<OnBinderDiedCallbackFunc> callback) override {
+ return {};
+ }
+
+ VhalClientResult<void> removeOnBinderDiedCallback(
+ [[maybe_unused]] std::shared_ptr<OnBinderDiedCallbackFunc> callback) override {
+ return {};
+ }
+
+ VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getAllPropConfigs() override {
+ return std::vector<std::unique_ptr<IHalPropConfig>>();
+ }
+
+ VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getPropConfigs(
+ [[maybe_unused]] std::vector<int32_t> propIds) override {
+ return std::vector<std::unique_ptr<IHalPropConfig>>();
+ }
+
+ std::unique_ptr<ISubscriptionClient> getSubscriptionClient(
+ [[maybe_unused]] std::shared_ptr<ISubscriptionCallback> callback) override {
+ return nullptr;
+ }
+};
+
class FakeRemoteTaskCallback : public BnRemoteTaskCallback {
public:
ScopedAStatus onRemoteTaskRequested(const std::string& clientId,
@@ -114,10 +187,13 @@
void setRetryWaitInMs(size_t retryWaitInMs) { mService->setRetryWaitInMs(retryWaitInMs); }
+ ScopedAStatus getDeviceIdWithClient(IVhalClient& vhalClient, std::string* deviceId) {
+ return mService->getDeviceIdWithClient(vhalClient, deviceId);
+ }
+
private:
std::unique_ptr<MockGrpcClientStub> mGrpcWakeupClientStub;
std::shared_ptr<RemoteAccessService> mService;
- MockClientReader<GetRemoteTasksResponse>* mMockTaskReader;
};
TEST_F(RemoteAccessServiceUnitTest, TestGetWakeupServiceName) {
@@ -282,6 +358,15 @@
std::this_thread::sleep_for(std::chrono::milliseconds(150));
}
+TEST_F(RemoteAccessServiceUnitTest, testGetDeviceId) {
+ std::string deviceId;
+
+ FakeVhalClient vhalClient;
+
+ ASSERT_TRUE(getDeviceIdWithClient(vhalClient, &deviceId).isOk());
+ ASSERT_EQ(deviceId, kTestVin);
+}
+
} // namespace remoteaccess
} // namespace automotive
} // namespace hardware
diff --git a/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp b/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp
deleted file mode 100644
index 6b97840..0000000
--- a/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2022 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 "RemoteAccessService.h"
-
-#include <android/binder_status.h>
-#include <grpc++/grpc++.h>
-#include <utils/Log.h>
-#include <chrono>
-#include <thread>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace remoteaccess {
-
-namespace {
-
-using ::aidl::android::hardware::automotive::remoteaccess::ApState;
-using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
-using ::android::base::ScopedLockAssertion;
-using ::grpc::ClientContext;
-using ::grpc::ClientReaderInterface;
-using ::grpc::Status;
-using ::grpc::StatusCode;
-using ::ndk::ScopedAStatus;
-
-const std::string WAKEUP_SERVICE_NAME = "com.google.vehicle.wakeup";
-
-std::vector<uint8_t> stringToBytes(const std::string& s) {
- const char* data = s.data();
- return std::vector<uint8_t>(data, data + s.size());
-}
-
-ScopedAStatus rpcStatusToScopedAStatus(const Status& status, const std::string& errorMsg) {
- return ScopedAStatus::fromServiceSpecificErrorWithMessage(
- status.error_code(), (errorMsg + ", error: " + status.error_message()).c_str());
-}
-
-} // namespace
-
-RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub)
- : mGrpcStub(grpcStub){};
-
-RemoteAccessService::~RemoteAccessService() {
- maybeStopTaskLoop();
-}
-
-void RemoteAccessService::maybeStartTaskLoop() {
- std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
- if (mTaskLoopRunning) {
- return;
- }
-
- mThread = std::thread([this]() { runTaskLoop(); });
-
- mTaskLoopRunning = true;
-}
-
-void RemoteAccessService::maybeStopTaskLoop() {
- std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
- if (!mTaskLoopRunning) {
- return;
- }
-
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- // Try to stop the reading stream.
- if (mGetRemoteTasksContext) {
- mGetRemoteTasksContext->TryCancel();
- mGetRemoteTasksContext.reset();
- }
- mTaskWaitStopped = true;
- mCv.notify_all();
- }
- if (mThread.joinable()) {
- mThread.join();
- }
-
- mTaskLoopRunning = false;
-}
-
-void RemoteAccessService::runTaskLoop() {
- GetRemoteTasksRequest request = {};
- std::unique_ptr<ClientReaderInterface<GetRemoteTasksResponse>> reader;
- while (true) {
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mGetRemoteTasksContext.reset(new ClientContext());
- reader = mGrpcStub->GetRemoteTasks(mGetRemoteTasksContext.get(), request);
- }
- GetRemoteTasksResponse response;
- while (reader->Read(&response)) {
- std::shared_ptr<IRemoteTaskCallback> callback;
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- callback = mRemoteTaskCallback;
- }
- if (callback == nullptr) {
- continue;
- }
- ScopedAStatus callbackStatus = callback->onRemoteTaskRequested(
- response.clientid(), stringToBytes(response.data()));
- if (!callbackStatus.isOk()) {
- ALOGE("Failed to call onRemoteTaskRequested callback, status: %d, message: %s",
- callbackStatus.getStatus(), callbackStatus.getMessage());
- }
- }
- Status status = reader->Finish();
-
- ALOGE("GetRemoteTasks stream breaks, code: %d, message: %s, sleeping for 10s and retry",
- status.error_code(), status.error_message().c_str());
- // The long lasting connection should not return. But if the server returns, retry after
- // 10s.
- {
- std::unique_lock lk(mLock);
- if (mCv.wait_for(lk, std::chrono::milliseconds(mRetryWaitInMs), [this] {
- ScopedLockAssertion lockAssertion(mLock);
- return mTaskWaitStopped;
- })) {
- // If the stopped flag is set, we are quitting, exit the loop.
- break;
- }
- }
- }
-}
-
-ScopedAStatus RemoteAccessService::getDeviceId(std::string* deviceId) {
- // TODO(b/241483300): Call VHAL to get VIN.
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::getWakeupServiceName(std::string* wakeupServiceName) {
- *wakeupServiceName = WAKEUP_SERVICE_NAME;
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::setRemoteTaskCallback(
- [[maybe_unused]] const std::shared_ptr<IRemoteTaskCallback>& callback) {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mRemoteTaskCallback = callback;
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::clearRemoteTaskCallback() {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mRemoteTaskCallback.reset();
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState) {
- ClientContext context;
- NotifyWakeupRequiredRequest request = {};
- request.set_iswakeuprequired(newState.isWakeupRequired);
- NotifyWakeupRequiredResponse response = {};
- Status status = mGrpcStub->NotifyWakeupRequired(&context, request, &response);
- if (!status.ok()) {
- return rpcStatusToScopedAStatus(status, "Failed to notify isWakeupRequired");
- }
-
- if (newState.isReadyForRemoteTask) {
- maybeStartTaskLoop();
- } else {
- maybeStopTaskLoop();
- }
- return ScopedAStatus::ok();
-}
-
-} // namespace remoteaccess
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/README.md b/automotive/remoteaccess/test_grpc_server/README.md
new file mode 100644
index 0000000..deea764
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/README.md
@@ -0,0 +1,7 @@
+# Test GRPC Server.
+
+A test GRPC server that implements wakeup_client.proto. This test server acts
+as a reference implementation for a remote wakeup client running on TCU. This
+reference server also implements wakeup_client_debug.proto which is the
+debugging interface. It is recommended that the actual implementation also
+implements this test interface for easier end-to-end testing.
diff --git a/automotive/remoteaccess/impl/default/test/Android.bp b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
similarity index 60%
copy from automotive/remoteaccess/impl/default/test/Android.bp
copy to automotive/remoteaccess/test_grpc_server/impl/Android.bp
index e92440f..8aab2e3 100644
--- a/automotive/remoteaccess/impl/default/test/Android.bp
+++ b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
@@ -13,31 +13,31 @@
// limitations under the License.
package {
- default_applicable_licenses: ["Android-Apache-2.0"],
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
}
-cc_test {
- name: "RemoteAccessServiceUnitTest",
+cc_binary {
+ name: "TestWakeupClientServer",
vendor: true,
- srcs: ["*.cpp"],
- whole_static_libs: [
- "RemoteAccessService",
- ],
+ srcs: ["src/*.cpp"],
+ local_include_dirs: ["include"],
shared_libs: [
- "libbinder_ndk",
+ "libbase",
"liblog",
"libutils",
"libgrpc++",
"libprotobuf-cpp-full",
],
- // libgrpc++.so is installed as root, require root to access it.
- require_root: true,
- static_libs: [
- "libgtest",
- "libgmock",
+ whole_static_libs: [
+ "wakeup_client_protos",
],
cflags: [
"-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
],
- test_suites: ["device-tests"],
}
diff --git a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
new file mode 100644
index 0000000..4c440b8
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <wakeup_client.grpc.pb.h>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <string>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+// A class to generate fake task for testing. Not required for real implementation. In real
+// implementation, the task should come from remote task server. This class is thread-safe.
+class FakeTaskGenerator final {
+ public:
+ GetRemoteTasksResponse generateTask();
+
+ private:
+ // Simulates the client ID for each task.
+ std::atomic<int> mCurrentClientId = 0;
+ constexpr static uint8_t DATA[] = {0xde, 0xad, 0xbe, 0xef};
+};
+
+// TaskQueue is thread-safe.
+class TaskQueue final {
+ public:
+ void add(const GetRemoteTasksResponse& response);
+ std::optional<GetRemoteTasksResponse> maybePopOne();
+ void waitForTask();
+ void stopWait();
+
+ private:
+ std::mutex mLock;
+ std::queue<GetRemoteTasksResponse> mTasks GUARDED_BY(mLock);
+ // A variable to notify mTasks is not empty.
+ std::condition_variable mTasksNotEmptyCv;
+ bool mStopped GUARDED_BY(mLock);
+};
+
+class TestWakeupClientServiceImpl final : public WakeupClient::Service {
+ public:
+ TestWakeupClientServiceImpl();
+
+ ~TestWakeupClientServiceImpl();
+
+ grpc::Status GetRemoteTasks(grpc::ServerContext* context, const GetRemoteTasksRequest* request,
+ grpc::ServerWriter<GetRemoteTasksResponse>* writer) override;
+
+ grpc::Status NotifyWakeupRequired(grpc::ServerContext* context,
+ const NotifyWakeupRequiredRequest* request,
+ NotifyWakeupRequiredResponse* response) override;
+
+ private:
+ // This is a thread for communicating with remote wakeup server (via network) and receive tasks
+ // from it.
+ std::thread mThread;
+ // A variable to notify server is stopping.
+ std::condition_variable mServerStoppedCv;
+ std::mutex mLock;
+ bool mServerStopped GUARDED_BY(mLock);
+
+ // Thread-safe. For test impl only.
+ FakeTaskGenerator mFakeTaskGenerator;
+ // Thread-sfae.
+ TaskQueue mTaskQueue;
+
+ void fakeTaskGenerateLoop();
+};
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
new file mode 100644
index 0000000..1eb87e2
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2022 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 "TestWakeupClientServiceImpl.h"
+
+#include <android-base/stringprintf.h>
+#include <utils/Log.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+namespace {
+
+using ::android::base::ScopedLockAssertion;
+using ::android::base::StringPrintf;
+using ::grpc::ServerContext;
+using ::grpc::ServerWriter;
+using ::grpc::Status;
+
+constexpr int kTaskIntervalInSec = 5;
+
+} // namespace
+
+GetRemoteTasksResponse FakeTaskGenerator::generateTask() {
+ int clientId = mCurrentClientId++;
+ GetRemoteTasksResponse response;
+ response.set_data(std::string(reinterpret_cast<const char*>(DATA), sizeof(DATA)));
+ std::string clientIdStr = StringPrintf("%d", clientId);
+ response.set_clientid(clientIdStr);
+ return response;
+}
+
+std::optional<GetRemoteTasksResponse> TaskQueue::maybePopOne() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ if (mTasks.size() == 0) {
+ return std::nullopt;
+ }
+ GetRemoteTasksResponse response = mTasks.front();
+ mTasks.pop();
+ return std::move(response);
+}
+void TaskQueue::add(const GetRemoteTasksResponse& task) {
+ // TODO (b/246841306): add timeout to tasks.
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mTasks.push(task);
+ mTasksNotEmptyCv.notify_all();
+}
+
+void TaskQueue::waitForTask() {
+ std::unique_lock<std::mutex> lock(mLock);
+ mTasksNotEmptyCv.wait(lock, [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mTasks.size() > 0 || mStopped;
+ });
+}
+
+void TaskQueue::stopWait() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mStopped = true;
+ mTasksNotEmptyCv.notify_all();
+}
+
+TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {
+ mThread = std::thread([this] { fakeTaskGenerateLoop(); });
+}
+
+TestWakeupClientServiceImpl::~TestWakeupClientServiceImpl() {
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mServerStopped = true;
+ mServerStoppedCv.notify_all();
+ }
+ mTaskQueue.stopWait();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void TestWakeupClientServiceImpl::fakeTaskGenerateLoop() {
+ // In actual implementation, this should communicate with the remote server and receives tasks
+ // from it. Here we simulate receiving one remote task every {kTaskIntervalInSec}s.
+ while (true) {
+ mTaskQueue.add(mFakeTaskGenerator.generateTask());
+ ALOGI("Sleeping for %d seconds until next task", kTaskIntervalInSec);
+
+ std::unique_lock lk(mLock);
+ if (mServerStoppedCv.wait_for(lk, std::chrono::seconds(kTaskIntervalInSec), [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mServerStopped;
+ })) {
+ // If the stopped flag is set, we are quitting, exit the loop.
+ return;
+ }
+ }
+}
+
+Status TestWakeupClientServiceImpl::GetRemoteTasks(ServerContext* context,
+ const GetRemoteTasksRequest* request,
+ ServerWriter<GetRemoteTasksResponse>* writer) {
+ ALOGD("GetRemoteTasks called");
+ while (true) {
+ mTaskQueue.waitForTask();
+
+ while (true) {
+ auto maybeTask = mTaskQueue.maybePopOne();
+ if (!maybeTask.has_value()) {
+ // No task left, loop again and wait for another task(s).
+ break;
+ }
+ // Loop through all the task in the queue but obtain lock for each element so we don't
+ // hold lock while writing the response.
+ const GetRemoteTasksResponse& response = maybeTask.value();
+ if (!writer->Write(response)) {
+ // Broken stream, maybe the client is shutting down.
+ ALOGW("Failed to deliver remote task to remote access HAL");
+ // The task failed to be sent, add it back to the queue. The order might change, but
+ // it is okay.
+ mTaskQueue.add(response);
+ return Status::CANCELLED;
+ }
+ }
+ }
+ return Status::OK;
+}
+
+Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context,
+ const NotifyWakeupRequiredRequest* request,
+ NotifyWakeupRequiredResponse* response) {
+ return Status::OK;
+}
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
new file mode 100644
index 0000000..bb03e70
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 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 <string>
+
+#include "TestWakeupClientServiceImpl.h"
+
+#include <grpc/grpc.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <utils/Log.h>
+
+using ::android::hardware::automotive::remoteaccess::TestWakeupClientServiceImpl;
+using ::grpc::Server;
+using ::grpc::ServerBuilder;
+using ::grpc::ServerWriter;
+
+void RunServer() {
+ std::string serverAddress(GRPC_SERVICE_ADDRESS);
+ std::shared_ptr<TestWakeupClientServiceImpl> service =
+ std::make_unique<TestWakeupClientServiceImpl>();
+
+ ServerBuilder builder;
+ builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials());
+ builder.RegisterService(service.get());
+ std::unique_ptr<Server> server(builder.BuildAndStart());
+ ALOGI("Test Remote Access GRPC Server listening on %s", serverAddress.c_str());
+ server->Wait();
+}
+
+int main(int argc, char** argv) {
+ RunServer();
+ return 0;
+}
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 63e9406..bf894f1 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -626,9 +626,9 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="aidl" optional="false">
<name>android.hardware.thermal</name>
- <version>2.0</version>
+ <version>1</version>
<interface>
<name>IThermal</name>
<instance>default</instance>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 6de9d03..cb77c7b 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -68,6 +68,8 @@
// does not depend on this HAL, hence it is not declared in any manifests or matrices.
"android.hardware.fastboot@1.0",
"android.hardware.fastboot@1.1",
+ // Fastboot AIDL
+ "android.hardware.fastboot",
// Deprecated HALs.
// HIDL
diff --git a/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp b/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
index bf1f1c8..61dae8b 100644
--- a/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
+++ b/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
@@ -266,7 +266,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
// Simulate the user taping ok.
@@ -309,7 +309,7 @@
static constexpr char test_prompt[] = "D\'oh!";
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG, getReturnCode(result));
@@ -322,7 +322,7 @@
static constexpr char test_prompt[] = "D\'oh!";
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG, getReturnCode(result));
@@ -334,7 +334,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
@@ -355,7 +355,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
@@ -377,7 +377,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
@@ -399,7 +399,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_
->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
@@ -424,7 +424,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
@@ -446,7 +446,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_
->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
@@ -469,7 +469,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
@@ -483,7 +483,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
@@ -496,7 +496,7 @@
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
- vector<uint8_t> prompt_text(test_prompt, test_prompt + sizeof(test_prompt));
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
diff --git a/fastboot/OWNERS b/fastboot/OWNERS
new file mode 100644
index 0000000..286b65f
--- /dev/null
+++ b/fastboot/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1228891
+dvander@google.com
+elsk@google.com
+dhavale@google.com
diff --git a/fastboot/aidl/Android.bp b/fastboot/aidl/Android.bp
new file mode 100644
index 0000000..a5735ab
--- /dev/null
+++ b/fastboot/aidl/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.fastboot",
+ vendor_available: true,
+ recovery_available: true,
+ srcs: ["android/hardware/fastboot/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ },
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl
similarity index 87%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl
index 02bf98a..b15d037 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,10 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+package android.hardware.fastboot;
+@Backing(type="byte") @VintfStability
+enum FileSystemType {
+ EXT4 = 0,
+ F2FS = 1,
+ RAW = 2,
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
similarity index 79%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
index 02bf98a..445fcde 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,14 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+package android.hardware.fastboot;
+@VintfStability
+interface IFastboot {
+ String doOemCommand(in String oemCmd);
+ void doOemSpecificErase();
+ int getBatteryVoltageFlashingThreshold();
+ boolean getOffModeChargeState();
+ android.hardware.fastboot.FileSystemType getPartitionType(in String partitionName);
+ String getVariant();
+ const int FAILURE_UNKNOWN = 1;
}
diff --git a/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl b/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl
new file mode 100644
index 0000000..b4027ec
--- /dev/null
+++ b/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fastboot;
+
+@VintfStability
+@Backing(type="byte")
+enum FileSystemType {
+ /**
+ * Fourth extended file system.
+ */
+ EXT4,
+ /**
+ * Flash Friendly File System.
+ */
+ F2FS,
+ /**
+ * Raw file system.
+ */
+ RAW,
+}
diff --git a/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl b/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl
new file mode 100644
index 0000000..abdc215
--- /dev/null
+++ b/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fastboot;
+
+import android.hardware.fastboot.FileSystemType;
+
+/**
+ * IFastboot interface implements vendor specific fastboot commands.
+ */
+@VintfStability
+interface IFastboot {
+ /**
+ * Status code for function.
+ * Operation failed due to unknown reason.
+ */
+ const int FAILURE_UNKNOWN = 1;
+ /**
+ * Executes a fastboot OEM command.
+ *
+ * @param oemCmd The oem command that is passed to the fastboot HAL.
+ * @return optional String if the operation is successful and output is expected
+ * for the command.
+ * @throws :
+ * - EX_ILLEGAL_ARGUMENT for bad arguments.
+ * - EX_UNSUPPORTED_OPERATION for unsupported commands.
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN for other errors.
+ */
+ String doOemCommand(in String oemCmd);
+
+ /**
+ * Executes an OEM specific erase after fastboot erase userdata.
+ *
+ * @throws :
+ * - EX_UNSUPPORTED_OPERATION if it is not supported.
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN for
+ * unknown error in oem specific command or other errors.
+ */
+ void doOemSpecificErase();
+
+ /**
+ * Returns the minimum battery voltage required for flashing in mV.
+ *
+ * @return Minimum batterery voltage (in mV) required for flashing to
+ * be successful.
+ * @throws :
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+ */
+ int getBatteryVoltageFlashingThreshold();
+
+ /**
+ * Returns whether off-mode-charging is enabled. If enabled, the device
+ * autoboots into a special mode when power is applied.
+ *
+ * @return Returns whether off-mode-charging is enabled.
+ * @throws :
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+ */
+ boolean getOffModeChargeState();
+
+ /**
+ * Returns the file system type of the partition. Implementation is only
+ * required for physical partitions that need to be wiped and reformatted.
+ * @param in partitionName Name of the partition.
+ * @return Returns the file system type of the partition. Type can be ext4,
+ * f2fs or raw.
+ * @throws :
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if the partition
+ * is invalid or does not require reformatting.
+ */
+ FileSystemType getPartitionType(in String partitionName);
+
+ /**
+ * Returns an OEM-defined string indicating the variant of the device, for
+ * example, US and ROW.
+ * @return Indicates the device variant.
+ * @throws :
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+ */
+ String getVariant();
+}
diff --git a/fastboot/aidl/default/Android.bp b/fastboot/aidl/default/Android.bp
new file mode 100644
index 0000000..5cd4542
--- /dev/null
+++ b/fastboot/aidl/default/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library {
+ name: "android.hardware.fastboot-impl-mock",
+ recovery: true,
+ srcs: [
+ "Fastboot.cpp",
+ ],
+ relative_install_path: "hw",
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libutils",
+ "libcutils",
+ "android.hardware.fastboot-V1-ndk",
+ ],
+}
diff --git a/fastboot/aidl/default/Fastboot.cpp b/fastboot/aidl/default/Fastboot.cpp
new file mode 100644
index 0000000..1ba73d3
--- /dev/null
+++ b/fastboot/aidl/default/Fastboot.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 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 "Fastboot.h"
+
+using ndk::ScopedAStatus;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace fastboot {
+
+ScopedAStatus Fastboot::getPartitionType(const std::string& in_partitionName,
+ FileSystemType* _aidl_return) {
+ if (in_partitionName.empty()) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Invalid partition name");
+ }
+ *_aidl_return = FileSystemType::RAW;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::doOemCommand(const std::string& in_oemCmd, std::string* _aidl_return) {
+ *_aidl_return = "";
+ if (in_oemCmd.empty()) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "Invalid command");
+ }
+ return ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_UNSUPPORTED_OPERATION, "Command not supported in default implementation");
+}
+
+ScopedAStatus Fastboot::getVariant(std::string* _aidl_return) {
+ *_aidl_return = "NA";
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::getOffModeChargeState(bool* _aidl_return) {
+ *_aidl_return = false;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::getBatteryVoltageFlashingThreshold(int32_t* _aidl_return) {
+ *_aidl_return = 0;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::doOemSpecificErase() {
+ return ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_UNSUPPORTED_OPERATION, "Command not supported in default implementation");
+}
+
+} // namespace fastboot
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/fastboot/aidl/default/Fastboot.h b/fastboot/aidl/default/Fastboot.h
new file mode 100644
index 0000000..48e2c38
--- /dev/null
+++ b/fastboot/aidl/default/Fastboot.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "aidl/android/hardware/fastboot/BnFastboot.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace fastboot {
+class Fastboot : public BnFastboot {
+ ::ndk::ScopedAStatus doOemCommand(const std::string& in_oemCmd,
+ std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus doOemSpecificErase() override;
+ ::ndk::ScopedAStatus getBatteryVoltageFlashingThreshold(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getOffModeChargeState(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getPartitionType(
+ const std::string& in_partitionName,
+ ::aidl::android::hardware::fastboot::FileSystemType* _aidl_return) override;
+ ::ndk::ScopedAStatus getVariant(std::string* _aidl_return) override;
+};
+
+} // namespace fastboot
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
index 7fab555..ea9f3a4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
@@ -36,9 +36,6 @@
interface IImsMediaSession {
oneway void setListener(in android.hardware.radio.ims.media.IImsMediaSessionListener sessionListener);
oneway void modifySession(in android.hardware.radio.ims.media.RtpConfig config);
- oneway void addConfig(in android.hardware.radio.ims.media.RtpConfig config);
- oneway void deleteConfig(in android.hardware.radio.ims.media.RtpConfig config);
- oneway void confirmConfig(in android.hardware.radio.ims.media.RtpConfig config);
oneway void sendDtmf(char dtmfDigit, int duration);
oneway void startDtmf(char dtmfDigit);
oneway void stopDtmf();
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
index 6159780..f03b29e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
@@ -34,10 +34,7 @@
package android.hardware.radio.ims.media;
@VintfStability
interface IImsMediaSessionListener {
- oneway void onSessionChanged(android.hardware.radio.ims.media.RtpSessionState state);
oneway void onModifySessionResponse(in android.hardware.radio.ims.media.RtpConfig config, android.hardware.radio.ims.media.RtpError error);
- oneway void onAddConfigResponse(in android.hardware.radio.ims.media.RtpConfig config, android.hardware.radio.ims.media.RtpError error);
- oneway void onConfirmConfigResponse(in android.hardware.radio.ims.media.RtpConfig config, android.hardware.radio.ims.media.RtpError error);
oneway void onFirstMediaPacketReceived(in android.hardware.radio.ims.media.RtpConfig config);
oneway void onHeaderExtensionReceived(in List<android.hardware.radio.ims.media.RtpHeaderExtension> extensions);
oneway void notifyMediaInactivity(android.hardware.radio.ims.media.MediaProtocolType packetType);
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
index d291f44..a8d2161 100644
--- a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
@@ -44,37 +44,6 @@
void modifySession(in RtpConfig config);
/**
- * Adds a new remote configuration to a RTP session during early media
- * scenarios where the IMS network could add more than one remote endpoint.
- *
- * @param config provides remote end point info and codec details
- */
- void addConfig(in RtpConfig config);
-
- /**
- * Deletes a remote configuration from a RTP session during early media
- * scenarios. A session shall have at least one config so this API shall
- * not delete the last config.
- *
- * @param config remote config to be deleted
- */
- void deleteConfig(in RtpConfig config);
-
- /**
- * Confirms a remote configuration for a Rtp session for early media scenarios
- * when there are more than one remote configs. All other early remote configs
- * (potentially including the config created as part of openSession) are auto
- * deleted when one config is confirmed.
- * Confirming a remote configuration is necessary only if additional
- * configurations were created.
- * New remote configurations cannot be added after a remote configuration is
- * confirmed.
- *
- * @param config remote config to be confirmed
- */
- void confirmConfig(in RtpConfig config);
-
- /**
* Send DTMF digit until the duration expires.
*
* @param dtmfDigit single char having one of 12 values: 0-9, *, #
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
index 317aeb7..d40da64 100644
--- a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
@@ -21,7 +21,6 @@
import android.hardware.radio.ims.media.RtpConfig;
import android.hardware.radio.ims.media.RtpError;
import android.hardware.radio.ims.media.RtpHeaderExtension;
-import android.hardware.radio.ims.media.RtpSessionState;
/**
* Interface declaring listener functions for unsolicited IMS media notifications per session.
@@ -29,13 +28,6 @@
@VintfStability
oneway interface IImsMediaSessionListener {
/**
- * Notifies whenever the session state changed.
- *
- * @param state RTP session state
- */
- void onSessionChanged(RtpSessionState state);
-
- /**
* Notifies the result of IImsMediaSession#modifySession() API.
*
* @param config The RTP config passed in IImsMediaSession#modifySession() API
@@ -48,30 +40,6 @@
void onModifySessionResponse(in RtpConfig config, RtpError error);
/**
- * Notifies the result of IImsMediaSession#addConfig() API.
- *
- * @param config The RTP config passed in IImsMediaSession#addConfig() API
- * @param error RtpError.NONE in case of success else one of the following
- * RtpError :INVALID_PARAM
- * RtpError :INTERNAL_ERR
- * RtpError :NO_MEMORY
- * RtpError :NO_RESOURCES
- * RtpError :PORT_UNAVAILABLE
- */
- void onAddConfigResponse(in RtpConfig config, RtpError error);
-
- /**
- * Notifies the result of IImsMediaSession#confirmConfig() API.
- *
- * @param config The RtpConfig passed in IImsMediaSession#confirmConfig() API
- * @param error RtpError.NONE in case of success else one of the following
- * RtpError :INVALID_PARAM
- * RtpError :INTERNAL_ERR
- * RtpError :NO_RESOURCES
- */
- void onConfirmConfigResponse(in RtpConfig config, RtpError error);
-
- /**
* Indicates when the first Rtp media packet is received by the UE during ring
* back, call hold or early media scenarios. This is sent only if the packet is
* received on the active remote configuration.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index 6954d65..6854851 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -49,8 +49,16 @@
* "security_level" : "tee" / "strongbox",
* "fused": 1 / 0, ; 1 if secure boot is enforced for the processor that the IRPC
* ; implementation is contained in. 0 otherwise.
- * "cert_type": "widevine" / "keymint"
+ * "cert_type": CertificateType;
* }
+ *
+ * ; A tstr identifying the type of certificate. The set of supported certificate types may
+ * ; be extended without requiring a version bump of the HAL. Custom certificate types may
+ * ; be used, but the provisioning server may reject the request for an unknown certificate
+ * ; type. The currently defined certificate types are:
+ * ; - "widevine"
+ * ; - "keymint"
+ * CertificateType = tstr
*/
byte[] deviceInfo;
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 926d105..2e4fc15 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -624,9 +624,15 @@
*
* o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
*
- * o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be less than
- * the current secure timestamp (which is a monotonic timer counting milliseconds since
- * boot.)
+ * o If the device has a source of secure time, then the timestamp in the auth token plus the
+ * value of the Tag::AUTH_TIMEOUT must be greater than the current secure timestamp (which
+ * is a monotonic timer counting milliseconds since boot).
+ *
+ * o If the device does not have a source of secure time, then the timestamp check should be
+ * performed on the first update(), updateAad() or finish() invocation for the operation,
+ * using the timeStampToken parameter provided on the invocation to indicate the current
+ * timestamp. It may optionally also be performed on subsequent update() / updateAad() /
+ * finish() invocations.
*
* If any of these conditions are not met, begin() must return
* ErrorCode::KEY_USER_NOT_AUTHENTICATED.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index c30c183..82c8a0d 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -40,31 +40,7 @@
*
* == Authorization Enforcement ==
*
- * Key authorization enforcement is performed primarily in begin(). The one exception is the
- * case where the key has:
- *
- * o One or more Tag::USER_SECURE_IDs, and
- *
- * o Does not have a Tag::AUTH_TIMEOUT
- *
- * In this case, the key requires an authorization per operation, and the update method must
- * receive a non-null and valid HardwareAuthToken. For the auth token to be valid, all of the
- * following has to be true:
- *
- * o The HMAC field must validate correctly.
- *
- * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
- * the secure ID values in the token.
- *
- * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
- *
- * o The challenge field in the auth token must contain the value returned from
- * IKeyMintDevice::begin(), given by the challenge field of the BeginResult structure.
- *
- * If any of these conditions are not met, updateAad() must return
- * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
- *
- * The caller must provide the auth token on every call to updateAad(), update() and finish().
+ * See the Authorization Enforcement section for the update() method.
*
*
* For GCM encryption, the AEAD tag must be appended to the ciphertext by finish(). During
@@ -104,16 +80,22 @@
*
* == Authorization Enforcement ==
*
- * Key authorization enforcement is performed primarily in IKeyMintDevice::begin(). The one
- * exception is the case where the key has:
+ * Key authorization enforcement is performed primarily in IKeyMintDevice::begin(). There are
+ * two exceptions to this:
*
- * o One or more Tag::USER_SECURE_IDs, and
+ * 1) Key with USER_SECURE_IDs but no AUTH_TIMEOUT
*
- * o Does not have a Tag::AUTH_TIMEOUT
+ * 2) Key with USER_SECURE_IDs and AUTH_TIMEOUT, but the device does not support secure time.
*
- * In this case, the key requires an authorization per operation, and the update method must
- * receive a non-empty and valid HardwareAuthToken. For the auth token to be valid, all of the
- * following has to be true:
+ * The first exception is the case where the key:
+ *
+ * o Has one or more Tag::USER_SECURE_IDs, and
+ *
+ * o Does not have a Tag::AUTH_TIMEOUT
+ *
+ * In this case, the key requires an authorization per operation, and update() / updateAad() /
+ * finish() methods must receive a non-null and valid HardwareAuthToken. For the auth token to
+ * be valid, all of the following has to be true:
*
* o The HMAC field must validate correctly.
*
@@ -125,10 +107,47 @@
* o The challenge field in the auth token must contain the challenge value contained in the
* BeginResult returned from IKeyMintDevice::begin().
*
- * If any of these conditions are not met, update() must return
+ * If any of these conditions are not met, the method must return
* ErrorCode::KEY_USER_NOT_AUTHENTICATED.
*
- * The caller must provide the auth token on every call to update() and finish().
+ * The caller must provide the auth token on every call to update(), updateAad() and finish().
+ *
+ *
+ * The second exception is the case where the key:
+ *
+ * o Has one or more Tag::USER_SECURE_IDs, and
+ *
+ * o Has a Tag::AUTH_TIMEOUT value, but the device does not have a source of secure time (as
+ * indicated by the KeyMintHardwareInfo.timestampTokenRequired field).
+ *
+ * In this case, the key requires an per-operation authorization on the first call to update(),
+ * updateAad() or finish() for the operation, using the provided timeStampToken as a source of
+ * secure time. For this timeStampToken to be valid, all of the following has to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o The challenge field in the auth token must contain the challenge value contained in the
+ * BeginResult returned from IKeyMintDevice::begin().
+ *
+ * The resulting secure time value is then used to authenticate the HardwareAuthToken. For the
+ * auth token to be valid, all of the following has to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+ * the secure ID values in the token.
+ *
+ * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+ *
+ * o The challenge field in the auth token must contain the challenge value contained in the
+ * BeginResult returned from IKeyMintDevice::begin().
+ *
+ * o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be greater
+ * than the provided secure timestamp.
+
+ * If any of these conditions are not met, the method must return
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
*
* -- RSA keys --
*
@@ -187,24 +206,7 @@
* Key authorization enforcement is performed primarily in begin(). The exceptions are
* authorization per operation keys and confirmation-required keys.
*
- * Authorization per operation keys are the case where the key has one or more
- * Tag::USER_SECURE_IDs, and does not have a Tag::AUTH_TIMEOUT. In this case, the key requires
- * an authorization per operation, and the finish method must receive a non-empty and valid
- * authToken. For the auth token to be valid, all of the following has to be true:
- *
- * o The HMAC field must validate correctly.
- *
- * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
- * the secure ID values in the token.
- *
- * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
- *
- * o The challenge field in the auth token must contain the operation challenge.
- *
- * If any of these conditions are not met, update() must return
- * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
- *
- * The caller must provide the auth token on every call to update() and finish().
+ * Authorization per operation keys must be authorized as described for the update() method.
*
* Confirmation-required keys are keys that were generated with
* Tag::TRUSTED_CONFIRMATION_REQUIRED. For these keys, when doing a signing operation the
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index c2acbed..77df99f 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -29,7 +29,7 @@
* validate the request and create certificates.
*
* This interface does not provide any way to use the generated and certified key pairs. It's
- * intended to be implemented by a HAL service that does other things with keys (e.g. Keymint).
+ * intended to be implemented by a HAL service that does other things with keys (e.g. KeyMint).
*
* The root of trust for secure provisioning is something called the Device Identifier Composition
* Engine (DICE) Chain. The DICE Chain is a chain of certificates, represented as COSE_Sign1 objects
@@ -79,9 +79,9 @@
* While a proper DICE Chain, as described above, reflects the complete boot sequence from boot ROM
* to the secure area image of the IRemotelyProvisionedComponent, it's also possible to use a
* "degenerate" DICE Chain which consists only of a single, self-signed certificate containing the
- * public key of a hardware-bound key pair. This is an appopriate solution for devices which haven't
- * implemented everything necessary to produce a proper DICE Chain, but can derive a unique key pair
- * in the secure area. In this degenerate case, UDS_Pub is the same as CDI_Leaf_Pub.
+ * public key of a hardware-bound key pair. This is an appropriate solution for devices which
+ * haven't implemented everything necessary to produce a proper DICE Chain, but can derive a unique
+ * key pair in the secure area. In this degenerate case, UDS_Pub is the same as CDI_Leaf_Pub.
*
* DICE Chain Privacy
* ==================
@@ -151,7 +151,8 @@
/**
* This method has been removed in version 3 of the HAL. The header is kept around for
- * backwards compatibility purposes. Calling this method should return STATUS_REMOVED on v3.
+ * backwards compatibility purposes. From v3, this method should raise a
+ * ServiceSpecificException with an error code of STATUS_REMOVED.
*
* For v1 and v2 implementations:
* generateCertificateRequest creates a certificate request to be sent to the provisioning
@@ -170,7 +171,7 @@
* If testMode is false, the keysToCertify array must not contain any keys flagged as
* test keys. Otherwise, the method must return STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
*
- * @param in endpointEncryptionKey contains an X22519 public key which will be used to encrypt
+ * @param in endpointEncryptionKey contains an X25519 public key which will be used to encrypt
* the BCC. For flexibility, this is represented as a certificate chain, represented as a
* CBOR array of COSE_Sign1 objects, ordered from root to leaf. The leaf contains the
* X25519 encryption key, each other element is an Ed25519 key signing the next in the
@@ -197,7 +198,7 @@
* -2 : bstr ; Ed25519 public key
* }
*
- * SignatureKeyP256 = {
+ * SignatureKeyP256 = { ; COSE_Key
* 1 : 2, ; Key type : EC2
* 3 : AlgorithmES256, ; Algorithm
* -1 : 1, ; Curve: P256
@@ -227,7 +228,7 @@
* 2 : bstr ; KID : EEK ID
* 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
* -1 : 4, ; Curve : X25519
- * -2 : bstr ; Ed25519 public key
+ * -2 : bstr ; X25519 public key
* }
*
* EekP256 = { ; COSE_Key
@@ -246,8 +247,8 @@
* payload: bstr .cbor EekX25519 / .cbor EekP256
* ]
*
- * AlgorithmES256 = -7
- * AlgorithmEdDSA = -8
+ * AlgorithmES256 = -7 ; RFC 8152 section 8.1
+ * AlgorithmEdDSA = -8 ; RFC 8152 section 8.2
*
* If the contents of endpointEncryptionKey do not match the SignedEek structure above,
* the method must return STATUS_INVALID_EEK.
@@ -256,7 +257,7 @@
* in the chain, which implies that it must not attempt to validate the signature.
*
* If testMode is false, the method must validate the chain signatures, and must verify
- * that the public key in the root certifictate is in its pre-configured set of
+ * that the public key in the root certificate is in its pre-configured set of
* authorized EEK root keys. If the public key is not in the database, or if signature
* verification fails, the method must return STATUS_INVALID_EEK.
*
@@ -270,7 +271,7 @@
* @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
* authenticate the keysToSign (see keysToSignMac output argument).
*
- * @return The of KeysToSign in the CertificateRequest structure. Specifically, it contains:
+ * @return The MAC of KeysToSign in the CertificateRequest structure. Specifically, it contains:
*
* HMAC-256(EK_mac, .cbor KeysToMacStructure)
*
@@ -365,7 +366,7 @@
* ; intermediate certificates between Root and Leaf.
* ]
*
- * ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
+ * ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or EdDSA)
* X509Certificate = bstr
*
* ; The DICE Chain contains measurements about the device firmware.
@@ -378,8 +379,8 @@
* ; Last certificate corresponds to KeyMint's DICE key.
* ]
*
- * ; This is the signed payload for each entry in the DCC. Note that the "Configuration
- * ; Input Values" described by the Open Profile are not used here. Instead, the Dcc
+ * ; This is the signed payload for each entry in the DICE chain. Note that the "Configuration
+ * ; Input Values" described by the Open Profile are not used here. Instead, the DICE chain
* ; defines its own configuration values for the Configuration Descriptor field. See
* ; the Open Profile for DICE for more details on the fields. SHA256 and SHA512 are acceptable
* ; hash algorithms. The digest bstr values in the payload are the digest values without any
@@ -408,8 +409,8 @@
* -4670551 : bstr, ; Mode
* }
*
- * ; Each entry in the Dcc is a DiceChainEntryPayload signed by the key from the previous entry
- * ; in the Dcc array.
+ * ; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
+ * ; entry in the DICE chain array.
* DiceChainEntry = [ ; COSE_Sign1 (untagged)
* protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
* unprotected: {},
diff --git a/thermal/OWNERS b/thermal/OWNERS
new file mode 100644
index 0000000..7229b22
--- /dev/null
+++ b/thermal/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 826709
+
+# ADPF virtual team
+lpy@google.com
+wvw@google.com
diff --git a/thermal/aidl/Android.bp b/thermal/aidl/Android.bp
new file mode 100644
index 0000000..b132746
--- /dev/null
+++ b/thermal/aidl/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.thermal",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/thermal/*.aidl",
+ ],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: true,
+ },
+ java: {
+ platform_apis: true,
+ },
+ },
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
similarity index 85%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
index 02bf98a..50be508 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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
+1 * 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,
@@ -31,11 +31,10 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+package android.hardware.thermal;
+@VintfStability
+parcelable CoolingDevice {
+ android.hardware.thermal.CoolingType type;
+ String name;
+ long value;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
similarity index 85%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
index 02bf98a..57c8939 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,18 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
+package android.hardware.thermal;
@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+enum CoolingType {
+ FAN = 0,
+ BATTERY = 1,
+ CPU = 2,
+ GPU = 3,
+ MODEM = 4,
+ NPU = 5,
+ COMPONENT = 6,
+ TPU = 7,
+ POWER_AMPLIFIER = 8,
+ DISPLAY = 9,
+ SPEAKER = 10,
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
similarity index 60%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
index 02bf98a..0aed5ec 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,16 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+package android.hardware.thermal;
+@VintfStability
+interface IThermal {
+ android.hardware.thermal.CoolingDevice[] getCoolingDevices();
+ android.hardware.thermal.CoolingDevice[] getCoolingDevicesWithType(in android.hardware.thermal.CoolingType type);
+ android.hardware.thermal.Temperature[] getTemperatures();
+ android.hardware.thermal.Temperature[] getTemperaturesWithType(in android.hardware.thermal.TemperatureType type);
+ android.hardware.thermal.TemperatureThreshold[] getTemperatureThresholds();
+ android.hardware.thermal.TemperatureThreshold[] getTemperatureThresholdsWithType(in android.hardware.thermal.TemperatureType type);
+ void registerThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
+ void registerThermalChangedCallbackWithType(in android.hardware.thermal.IThermalChangedCallback callback, in android.hardware.thermal.TemperatureType type);
+ void unregisterThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
similarity index 87%
rename from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
rename to thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
index 02bf98a..6b3f922 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,8 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+package android.hardware.thermal;
+@VintfStability
+interface IThermalChangedCallback {
+ oneway void notifyThrottling(in android.hardware.thermal.Temperature temperature);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl
similarity index 85%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl
index 02bf98a..7156415 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,11 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+package android.hardware.thermal;
+@VintfStability
+parcelable Temperature {
+ android.hardware.thermal.TemperatureType type;
+ String name;
+ float value;
+ android.hardware.thermal.ThrottlingSeverity throttlingStatus;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl
similarity index 85%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl
index 02bf98a..6da561f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,11 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+package android.hardware.thermal;
+@VintfStability
+parcelable TemperatureThreshold {
+ android.hardware.thermal.TemperatureType type;
+ String name;
+ float[] hotThrottlingThresholds;
+ float[] coldThrottlingThresholds;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
similarity index 82%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
index 02bf98a..c6a08c1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,22 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
+package android.hardware.thermal;
@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+enum TemperatureType {
+ UNKNOWN = -1,
+ CPU = 0,
+ GPU = 1,
+ BATTERY = 2,
+ SKIN = 3,
+ USB_PORT = 4,
+ POWER_AMPLIFIER = 5,
+ BCL_VOLTAGE = 6,
+ BCL_CURRENT = 7,
+ BCL_PERCENTAGE = 8,
+ NPU = 9,
+ TPU = 10,
+ DISPLAY = 11,
+ MODEM = 12,
+ SOC = 13,
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
similarity index 87%
copy from radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
copy to thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
index 02bf98a..e86b581 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,11 +31,14 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.radio.ims.media;
+package android.hardware.thermal;
@Backing(type="int") @VintfStability
-enum RtpSessionState {
- OPEN = 0,
- ACTIVE = 1,
- SUSPENDED = 2,
- CLOSED = 3,
+enum ThrottlingSeverity {
+ NONE = 0,
+ LIGHT = 1,
+ MODERATE = 2,
+ SEVERE = 3,
+ CRITICAL = 4,
+ EMERGENCY = 5,
+ SHUTDOWN = 6,
}
diff --git a/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl b/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl
new file mode 100644
index 0000000..6d974a5
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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
+ *
+1 * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal;
+
+import android.hardware.thermal.CoolingType;
+
+@VintfStability
+parcelable CoolingDevice {
+ /**
+ * This cooling device type, CPU, GPU, BATTERY, and etc.
+ */
+ CoolingType type;
+ /**
+ * Name of this cooling device.
+ * All cooling devices of the same "type" must have a different "name".
+ * The name is usually defined in kernel device tree, and this is for client
+ * logging purpose.
+ */
+ String name;
+ /**
+ * Current throttle state of the cooling device. The value can any unsigned integer
+ * numbers between 0 and max_state defined in its driver, usually representing the
+ * associated device's power state. 0 means device is not in throttling, higher value
+ * means deeper throttling.
+ */
+ long value;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpSessionState.aidl b/thermal/aidl/android/hardware/thermal/CoolingType.aidl
similarity index 61%
rename from radio/aidl/android/hardware/radio/ims/media/RtpSessionState.aidl
rename to thermal/aidl/android/hardware/thermal/CoolingType.aidl
index 57ba69a..1b430d2 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtpSessionState.aidl
+++ b/thermal/aidl/android/hardware/thermal/CoolingType.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,17 +14,23 @@
* limitations under the License.
*/
-package android.hardware.radio.ims.media;
+package android.hardware.thermal;
+/**
+ * Device cooling device types
+ */
@VintfStability
@Backing(type="int")
-enum RtpSessionState {
- /** The RTP session is opened and media flow is not started */
- OPEN = 0,
- /** The RTP session has active media flow */
- ACTIVE = 1,
- /** The RTP session is suspended */
- SUSPENDED = 2,
- /** The RTP session is closed */
- CLOSED = 3,
+enum CoolingType {
+ FAN,
+ BATTERY,
+ CPU,
+ GPU,
+ MODEM,
+ NPU,
+ COMPONENT,
+ TPU,
+ POWER_AMPLIFIER,
+ DISPLAY,
+ SPEAKER,
}
diff --git a/thermal/aidl/android/hardware/thermal/IThermal.aidl b/thermal/aidl/android/hardware/thermal/IThermal.aidl
new file mode 100644
index 0000000..8b79cb4
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/IThermal.aidl
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal;
+
+import android.hardware.thermal.CoolingDevice;
+import android.hardware.thermal.CoolingType;
+import android.hardware.thermal.IThermalChangedCallback;
+import android.hardware.thermal.Temperature;
+import android.hardware.thermal.TemperatureThreshold;
+import android.hardware.thermal.TemperatureType;
+
+@VintfStability
+interface IThermal {
+ /**
+ * Retrieves the cooling devices information.
+ *
+ * @return devices If succeed, it's filled with the
+ * current cooling device information. The order of built-in cooling
+ * devices in the list must be kept the same regardless the number
+ * of calls to this method even if they go offline, if these devices
+ * exist on boot. The method always returns and never removes from
+ * the list such cooling devices.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, getMessage() must be populated with the human-readable
+ * error message.
+ */
+ CoolingDevice[] getCoolingDevices();
+
+ /**
+ * Retrieves the cooling devices information of a given CoolingType.
+ *
+ * @param type the CoolingDevice such as CPU/GPU.
+ *
+ * @return devices If succeed, it's filled with the current
+ * cooling device information. The order of built-in cooling
+ * devices in the list must be kept the same regardless of the number
+ * of calls to this method even if they go offline, if these devices
+ * exist on boot. The method always returns and never removes from
+ * the list such cooling devices.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ CoolingDevice[] getCoolingDevicesWithType(in CoolingType type);
+
+ /**
+ * Retrieves temperatures in Celsius.
+ *
+ * @return temperatures If succeed, it's filled with the
+ * current temperatures. The order of temperatures of built-in
+ * devices (such as CPUs, GPUs and etc.) in the list must be kept
+ * the same regardless the number of calls to this method even if
+ * they go offline, if these devices exist on boot. The method
+ * always returns and never removes such temperatures.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ Temperature[] getTemperatures();
+
+ /**
+ * Retrieves temperatures in Celsius with a given TemperatureType.
+ *
+ * @param type the TemperatureType such as battery or skin.
+ *
+ * @return temperatures If succeed, it's filled with the
+ * current temperatures. The order of temperatures of built-in
+ * devices (such as CPUs, GPUs and etc.) in the list must be kept
+ * the same regardless of the number of calls to this method even if
+ * they go offline, if these devices exist on boot. The method
+ * always returns and never removes such temperatures.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ Temperature[] getTemperaturesWithType(in TemperatureType type);
+
+ /**
+ * Retrieves static temperature thresholds in Celsius.
+ *
+ * @return temperatureThresholds If succeed, it's filled with the
+ * temperatures thresholds. The order of temperatures of built-in
+ * devices (such as CPUs, GPUs and etc.) in the list must be kept
+ * the same regardless of the number of calls to this method even if
+ * they go offline, if these devices exist on boot. The method
+ * always returns and never removes such temperatures. The thresholds
+ * are returned as static values and must not change across calls. The actual
+ * throttling state is determined in device thermal mitigation policy/agorithm
+ * which might not be simple thresholds so these values Thermal HAL provided
+ * may not be accurate to detemin the throttling status. To get accurate
+ * throttling status, use getTemperatures or registerThermalChangedCallback
+ * and listen to the callback.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ TemperatureThreshold[] getTemperatureThresholds();
+
+ /**
+ * Retrieves static temperature thresholds in Celsius of a given temperature
+ * type.
+ *
+ * @param type the TemperatureType such as battery or skin.
+ *
+ * @return temperatureThresholds If succeed, it's filled with the
+ * temperatures thresholds. The order of temperatures of built-in
+ * devices (such as CPUs, GPUs and etc.) in the list must be kept
+ * the same regardless of the number of calls to this method even if
+ * they go offline, if these devices exist on boot. The method
+ * always returns and never removes such temperatures. The thresholds
+ * are returned as static values and must not change across calls. The actual
+ * throttling state is determined in device thermal mitigation policy/agorithm
+ * which might not be simple thresholds so these values Thermal HAL provided
+ * may not be accurate to detemin the throttling status. To get accurate
+ * throttling status, use getTemperatures or registerThermalChangedCallback
+ * and listen to the callback.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ TemperatureThreshold[] getTemperatureThresholdsWithType(in TemperatureType type);
+
+ /**
+ * Register an IThermalChangedCallback, used by the Thermal HAL to receive
+ * thermal events when thermal mitigation status changed.
+ * Multiple registrations with different IThermalChangedCallback must be allowed.
+ * Multiple registrations with same IThermalChangedCallback is not allowed, client
+ * should unregister the given IThermalChangedCallback first.
+ *
+ * @param callback the IThermalChangedCallback to use for receiving
+ * thermal events. if nullptr callback is given, the status code will be
+ * STATUS_BAD_VALUE and the operation will fail.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message. If callback is given nullptr, the returned status code
+ * will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+ * if callback is already registered, the returned status code will be
+ * STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+ */
+ void registerThermalChangedCallback(in IThermalChangedCallback callback);
+
+ /**
+ * Register an IThermalChangedCallback for a given TemperatureType, used by
+ * the Thermal HAL to receive thermal events when thermal mitigation status
+ * changed.
+ * Multiple registrations with different IThermalChangedCallback must be allowed.
+ * Multiple registrations with same IThermalChangedCallback is not allowed, client
+ * should unregister the given IThermalChangedCallback first.
+ *
+ * @param callback the IThermalChangedCallback to use for receiving
+ * thermal events. if nullptr callback is given, the status code will be
+ * STATUS_BAD_VALUE and the operation will fail.
+ * @param type the type to be filtered.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message. If callback is given nullptr, the returned status code
+ * will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+ * if callback is already registered, the returned status code will be
+ * STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+ */
+ void registerThermalChangedCallbackWithType(
+ in IThermalChangedCallback callback, in TemperatureType type);
+
+ /**
+ * Unregister an IThermalChangedCallback, used by the Thermal HAL
+ * to receive thermal events when thermal mitigation status changed.
+ *
+ * @param callback the IThermalChangedCallback to use for receiving
+ * thermal events. if nullptr callback is given, the status code will be
+ * STATUS_BAD_VALUE and the operation will fail.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message. If callback is given nullptr, the returned status code
+ * will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+ * if callback is not registered, the returned status code will be
+ * STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+ */
+ void unregisterThermalChangedCallback(in IThermalChangedCallback callback);
+}
diff --git a/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
new file mode 100644
index 0000000..6fe2dac
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal;
+
+import android.hardware.thermal.Temperature;
+
+/**
+ * IThermalChangedCallback send throttling notification to clients.
+ */
+@VintfStability
+interface IThermalChangedCallback {
+ /**
+ * Send a thermal throttling event to all ThermalHAL
+ * thermal event listeners.
+ *
+ * @param temperature The temperature associated with the
+ * throttling event.
+ */
+ oneway void notifyThrottling(in Temperature temperature);
+}
diff --git a/thermal/aidl/android/hardware/thermal/Temperature.aidl b/thermal/aidl/android/hardware/thermal/Temperature.aidl
new file mode 100644
index 0000000..f0041ed
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/Temperature.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal;
+
+import android.hardware.thermal.TemperatureType;
+import android.hardware.thermal.ThrottlingSeverity;
+
+@VintfStability
+parcelable Temperature {
+ /**
+ * This temperature's type.
+ */
+ TemperatureType type;
+ /**
+ * Name of this temperature matching the TemperatureThreshold.
+ * All temperatures of the same "type" must have a different "name",
+ * e.g., cpu0, battery. Clients use it to match with TemperatureThreshold
+ * struct.
+ */
+ String name;
+ /**
+ * For BCL, this is the current reading of the virtual sensor and the unit is
+ * millivolt, milliamp, percentage for BCL_VOLTAGE, BCL_CURRENT and BCL_PERCENTAGE
+ * respectively. For everything else, this is the current temperature in Celsius.
+ * If not available set by HAL to NAN.
+ */
+ float value;
+ /**
+ * The current throttling level of the sensor.
+ */
+ ThrottlingSeverity throttlingStatus;
+}
diff --git a/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl b/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl
new file mode 100644
index 0000000..9ecdab3
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal;
+
+import android.hardware.thermal.TemperatureType;
+
+@VintfStability
+parcelable TemperatureThreshold {
+ /**
+ * This temperature's type.
+ */
+ TemperatureType type;
+ /**
+ * Name of this temperature matching the Temperature struct.
+ * All temperatures of the same "type" must have a different "name",
+ * e.g., cpu0, battery. Clients use it to match Temperature struct.
+ */
+ String name;
+ /**
+ * Hot throttling temperature constant for this temperature sensor in
+ * level defined in ThrottlingSeverity including shutdown. Throttling
+ * happens when temperature >= threshold. If not available, set to NAN.
+ * Unit is same as Temperature's value.
+ * The number of thresholds must be the same as ThrottlingSeverity#len.
+ */
+ float[] hotThrottlingThresholds;
+ /**
+ * Cold throttling temperature constant for this temperature sensor in
+ * level defined in ThrottlingSeverity including shutdown. Throttling
+ * happens when temperature <= threshold. If not available, set to NAN.
+ * Unit is same as Temperature's value.
+ * The number of theresholds must be the same as ThrottlingSeverity#len.
+ */
+ float[] coldThrottlingThresholds;
+}
diff --git a/thermal/aidl/android/hardware/thermal/TemperatureType.aidl b/thermal/aidl/android/hardware/thermal/TemperatureType.aidl
new file mode 100644
index 0000000..aebe7ce
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/TemperatureType.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal;
+
+/**
+ * Device temperature types
+ */
+@VintfStability
+@Backing(type="int")
+enum TemperatureType {
+ UNKNOWN = -1,
+ CPU = 0,
+ GPU = 1,
+ BATTERY = 2,
+ SKIN = 3,
+ USB_PORT = 4,
+ POWER_AMPLIFIER = 5,
+ /**
+ * Battery Current Limit - virtual sensors
+ */
+ BCL_VOLTAGE = 6,
+ BCL_CURRENT = 7,
+ BCL_PERCENTAGE = 8,
+ /**
+ * Neural Processing Unit
+ */
+ NPU = 9,
+ TPU = 10,
+ DISPLAY = 11,
+ MODEM = 12,
+ SOC = 13,
+}
diff --git a/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl b/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl
new file mode 100644
index 0000000..29f0724
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal;
+
+/**
+ * Device throttling severity
+ */
+@VintfStability
+@Backing(type="int")
+enum ThrottlingSeverity {
+ /**
+ * Not under throttling.
+ */
+ NONE = 0,
+ /**
+ * Light throttling where UX is not impacted.
+ */
+ LIGHT,
+ /**
+ * Moderate throttling where UX is not largely impacted.
+ */
+ MODERATE,
+ /**
+ * Severe throttling where UX is largely impacted.
+ * Similar to 1.0 throttlingThreshold.
+ */
+ SEVERE,
+ /**
+ * Platform has done everything to reduce power.
+ */
+ CRITICAL,
+ /**
+ * Key components in platform are shutting down due to thermal condition.
+ * Device functionalities will be limited.
+ */
+ EMERGENCY,
+ /**
+ * Need shutdown immediately.
+ */
+ SHUTDOWN,
+}
diff --git a/thermal/aidl/default/Android.bp b/thermal/aidl/default/Android.bp
new file mode 100644
index 0000000..49a578b
--- /dev/null
+++ b/thermal/aidl/default/Android.bp
@@ -0,0 +1,49 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+ name: "android.hardware.thermal-service.example",
+ relative_install_path: "hw",
+ init_rc: [":android.hardware.thermal.example.rc"],
+ vintf_fragments: [":android.hardware.thermal.example.xml"],
+ vendor: true,
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "android.hardware.thermal-V1-ndk",
+ ],
+ srcs: [
+ "main.cpp",
+ "Thermal.cpp",
+ ],
+}
+
+filegroup {
+ name: "android.hardware.thermal.example.xml",
+ srcs: ["thermal-example.xml"],
+}
+
+filegroup {
+ name: "android.hardware.thermal.example.rc",
+ srcs: ["thermal-example.rc"],
+}
diff --git a/thermal/aidl/default/Thermal.cpp b/thermal/aidl/default/Thermal.cpp
new file mode 100644
index 0000000..5771e0e
--- /dev/null
+++ b/thermal/aidl/default/Thermal.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 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 "Thermal.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::thermal::impl::example {
+
+using ndk::ScopedAStatus;
+
+ScopedAStatus Thermal::getCoolingDevices(std::vector<CoolingDevice>* /* out_devices */) {
+ LOG(VERBOSE) << __func__;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getCoolingDevicesWithType(CoolingType in_type,
+ std::vector<CoolingDevice>* /* out_devices */) {
+ LOG(VERBOSE) << __func__ << " CoolingType: " << static_cast<int32_t>(in_type);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatures(std::vector<Temperature>* /* out_temperatures */) {
+ LOG(VERBOSE) << __func__;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperaturesWithType(TemperatureType in_type,
+ std::vector<Temperature>* /* out_temperatures */) {
+ LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast<int32_t>(in_type);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatureThresholds(
+ std::vector<TemperatureThreshold>* /* out_temperatureThresholds */) {
+ LOG(VERBOSE) << __func__;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatureThresholdsWithType(
+ TemperatureType in_type,
+ std::vector<TemperatureThreshold>* /* out_temperatureThresholds */) {
+ LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast<int32_t>(in_type);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::registerThermalChangedCallback(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback) {
+ LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback;
+ if (in_callback == nullptr) {
+ return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+ }
+ if (mCallbacks.find(in_callback) != mCallbacks.end()) {
+ return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+ }
+ mCallbacks.insert(in_callback);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::registerThermalChangedCallbackWithType(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback, TemperatureType in_type) {
+ LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback
+ << ", TemperatureType: " << static_cast<int32_t>(in_type);
+ if (in_callback == nullptr) {
+ return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+ }
+ if (mCallbacks.find(in_callback) != mCallbacks.end()) {
+ return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+ }
+ mCallbacks.insert(in_callback);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::unregisterThermalChangedCallback(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback) {
+ LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback;
+ bool found = false;
+ if (in_callback == nullptr) {
+ return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+ }
+ if (mCallbacks.find(in_callback) == mCallbacks.end()) {
+ return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+ }
+ mCallbacks.erase(in_callback);
+ return ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::thermal::impl::example
diff --git a/thermal/aidl/default/Thermal.h b/thermal/aidl/default/Thermal.h
new file mode 100644
index 0000000..788af4a
--- /dev/null
+++ b/thermal/aidl/default/Thermal.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <set>
+
+#include <aidl/android/hardware/thermal/BnThermal.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace impl {
+namespace example {
+
+class Thermal : public BnThermal {
+ public:
+ ndk::ScopedAStatus getCoolingDevices(std::vector<CoolingDevice>* out_devices) override;
+ ndk::ScopedAStatus getCoolingDevicesWithType(CoolingType in_type,
+ std::vector<CoolingDevice>* out_devices) override;
+
+ ndk::ScopedAStatus getTemperatures(std::vector<Temperature>* out_temperatures) override;
+ ndk::ScopedAStatus getTemperaturesWithType(TemperatureType in_type,
+ std::vector<Temperature>* out_temperatures) override;
+
+ ndk::ScopedAStatus getTemperatureThresholds(
+ std::vector<TemperatureThreshold>* out_temperatureThresholds) override;
+
+ ndk::ScopedAStatus getTemperatureThresholdsWithType(
+ TemperatureType in_type,
+ std::vector<TemperatureThreshold>* out_temperatureThresholds) override;
+
+ ndk::ScopedAStatus registerThermalChangedCallback(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback) override;
+ ndk::ScopedAStatus registerThermalChangedCallbackWithType(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback,
+ TemperatureType in_type) override;
+
+ ndk::ScopedAStatus unregisterThermalChangedCallback(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback) override;
+
+ private:
+ std::set<std::shared_ptr<IThermalChangedCallback>> mCallbacks;
+};
+
+} // namespace example
+} // namespace impl
+} // namespace thermal
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/thermal/aidl/default/main.cpp b/thermal/aidl/default/main.cpp
new file mode 100644
index 0000000..61d8ad0
--- /dev/null
+++ b/thermal/aidl/default/main.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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 "Thermal.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::thermal::impl::example::Thermal;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ std::shared_ptr<Thermal> thermal = ndk::SharedRefBase::make<Thermal>();
+
+ const std::string instance = std::string() + Thermal::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(thermal->asBinder().get(), instance.c_str());
+ CHECK(status == STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/thermal/aidl/default/thermal-example.rc b/thermal/aidl/default/thermal-example.rc
new file mode 100644
index 0000000..591ca03
--- /dev/null
+++ b/thermal/aidl/default/thermal-example.rc
@@ -0,0 +1,4 @@
+service vendor.thermal-example /vendor/bin/hw/android.hardware.thermal-service.example
+ class hal
+ user nobody
+ group system
diff --git a/thermal/aidl/default/thermal-example.xml b/thermal/aidl/default/thermal-example.xml
new file mode 100644
index 0000000..bdee744
--- /dev/null
+++ b/thermal/aidl/default/thermal-example.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.thermal</name>
+ <version>1</version>
+ <fqname>IThermal/default</fqname>
+ </hal>
+</manifest>
diff --git a/thermal/aidl/vts/Android.bp b/thermal/aidl/vts/Android.bp
new file mode 100644
index 0000000..b00eb33
--- /dev/null
+++ b/thermal/aidl/vts/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalThermalTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalThermalTargetTest.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ static_libs: [
+ "android.hardware.thermal-V1-ndk",
+ ],
+ test_suites: [
+ "vts",
+ ],
+}
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
new file mode 100644
index 0000000..b93250e
--- /dev/null
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2022 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 <algorithm>
+#include <chrono>
+#include <cmath>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+#define LOG_TAG "thermal_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/thermal/BnThermal.h>
+#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+#include <gtest/gtest.h>
+
+#include <unistd.h>
+
+namespace aidl::android::hardware::thermal {
+
+namespace {
+
+using ::android::sp;
+using android::hardware::thermal::CoolingDevice;
+using android::hardware::thermal::IThermal;
+using android::hardware::thermal::Temperature;
+using android::hardware::thermal::TemperatureType;
+
+using namespace std::string_literals;
+using namespace std::chrono_literals;
+
+static const Temperature kThrottleTemp = {
+ .type = TemperatureType::SKIN,
+ .name = "test temperature sensor",
+ .value = 98.6,
+ .throttlingStatus = ThrottlingSeverity::CRITICAL,
+};
+
+// Callback class for receiving thermal event notifications from main class
+class ThermalCallback : public BnThermalChangedCallback {
+ public:
+ ndk::ScopedAStatus notifyThrottling(const Temperature&) override {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mInvoke = true;
+ }
+ mNotifyThrottling.notify_all();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ template <typename R, typename P>
+ [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ bool r = mNotifyThrottling.wait_for(lock, duration, [this] { return this->mInvoke; });
+ mInvoke = false;
+ return r;
+ }
+
+ private:
+ std::mutex mMutex;
+ std::condition_variable mNotifyThrottling;
+ bool mInvoke = false;
+};
+
+// The main test class for THERMAL HIDL HAL.
+class ThermalAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
+ ASSERT_NE(binder, nullptr);
+ mThermal = IThermal::fromBinder(ndk::SpAIBinder(binder));
+
+ mThermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
+ ASSERT_NE(mThermalCallback, nullptr);
+ auto ret = mThermal->registerThermalChangedCallback(mThermalCallback);
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail if register again
+ ret = mThermal->registerThermalChangedCallback(mThermalCallback);
+ ASSERT_FALSE(ret.isOk());
+ ASSERT_TRUE(ret.getStatus() == STATUS_INVALID_OPERATION);
+ }
+
+ void TearDown() override {
+ auto ret = mThermal->unregisterThermalChangedCallback(mThermalCallback);
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail if unregister again
+ ret = mThermal->unregisterThermalChangedCallback(mThermalCallback);
+ ASSERT_FALSE(ret.isOk());
+ ASSERT_TRUE(ret.getStatus() == STATUS_INVALID_OPERATION);
+ }
+
+ protected:
+ std::shared_ptr<IThermal> mThermal;
+ std::shared_ptr<ThermalCallback> mThermalCallback;
+};
+
+// Test ThermalChangedCallback::notifyThrottling().
+// This just calls into and back from our local ThermalChangedCallback impl.
+TEST_P(ThermalAidlTest, NotifyThrottlingTest) {
+ std::shared_ptr<ThermalCallback> thermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
+ auto ret = thermalCallback->notifyThrottling(kThrottleTemp);
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_TRUE(thermalCallback->waitForCallback(200ms));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ Thermal, ThermalAidlTest,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
+ ::android::PrintInstanceNameToString);
+
+} // namespace
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
+
+} // namespace aidl::android::hardware::thermal