Merge "Add power efficiency hint for power hint session."
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index d6e6f50..4871058 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -100,6 +100,7 @@
"android/hardware/audio/core/MmapBufferDescriptor.aidl",
"android/hardware/audio/core/ModuleDebug.aidl",
"android/hardware/audio/core/StreamDescriptor.aidl",
+ "android/hardware/audio/core/SurroundSoundConfig.aidl",
],
imports: [
"android.hardware.common-V2",
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
index fd80715..163b7a0 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
@@ -34,4 +34,5 @@
package android.hardware.audio.core;
@VintfStability
interface IConfig {
+ android.hardware.audio.core.SurroundSoundConfig getSurroundSoundConfig();
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl
new file mode 100644
index 0000000..08a1537
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SurroundSoundConfig {
+ android.hardware.audio.core.SurroundSoundConfig.SurroundFormatFamily[] formatFamilies;
+ @VintfStability
+ parcelable SurroundFormatFamily {
+ android.media.audio.common.AudioFormatDescription primaryFormat;
+ android.media.audio.common.AudioFormatDescription[] subFormats;
+ }
+}
diff --git a/audio/aidl/android/hardware/audio/core/IConfig.aidl b/audio/aidl/android/hardware/audio/core/IConfig.aidl
index c7bb414..c8ba6be 100644
--- a/audio/aidl/android/hardware/audio/core/IConfig.aidl
+++ b/audio/aidl/android/hardware/audio/core/IConfig.aidl
@@ -16,9 +16,22 @@
package android.hardware.audio.core;
+import android.hardware.audio.core.SurroundSoundConfig;
+
/**
* This interface provides system-wide configuration parameters for audio I/O
* (by "system" here we mean the device running Android).
*/
@VintfStability
-interface IConfig {}
+interface IConfig {
+ /**
+ * Returns the surround sound configuration used for the Audio Policy
+ * Manager initial configuration.
+ *
+ * This method will only be called during the initialization of the Audio
+ * Policy Manager, and must always return the same result.
+ *
+ * @return The surround sound configuration
+ */
+ SurroundSoundConfig getSurroundSoundConfig();
+}
diff --git a/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl b/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl
new file mode 100644
index 0000000..eeda12a
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.audio.core;
+
+import android.media.audio.common.AudioFormatDescription;
+
+/**
+ * SurroundSoundConfig defines the multi-channel formats that can be enabled on
+ * (primarily TV) devices.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SurroundSoundConfig {
+ @VintfStability
+ parcelable SurroundFormatFamily {
+ /**
+ * A primaryFormat shall get an entry in the Surround Settings dialog on TV
+ * devices. There must be a corresponding Java ENCODING_... constant
+ * defined in AudioFormat.java, and a display name defined in
+ * AudioFormat.toDisplayName.
+ */
+ AudioFormatDescription primaryFormat;
+ /**
+ * List of formats that shall be equivalent to the primaryFormat from the
+ * users' point of view and don't need a dedicated Surround Settings
+ * dialog entry.
+ */
+ AudioFormatDescription[] subFormats;
+ }
+ SurroundFormatFamily[] formatFamilies;
+}
diff --git a/audio/aidl/default/Config.cpp b/audio/aidl/default/Config.cpp
index 3f7a3d3..0fdd5b4 100644
--- a/audio/aidl/default/Config.cpp
+++ b/audio/aidl/default/Config.cpp
@@ -13,7 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "AHAL_Module"
+#include <android-base/logging.h>
#include "core-impl/Config.h"
-namespace aidl::android::hardware::audio::core {} // namespace aidl::android::hardware::audio::core
+namespace aidl::android::hardware::audio::core {
+ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
+ SurroundSoundConfig surroundSoundConfig;
+ // TODO: parse from XML; for now, use empty config as default
+ *_aidl_return = std::move(surroundSoundConfig);
+ LOG(DEBUG) << __func__ << ": returning " << _aidl_return->toString();
+ return ndk::ScopedAStatus::ok();
+}
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Config.h b/audio/aidl/default/include/core-impl/Config.h
index b62a14b..4555efd 100644
--- a/audio/aidl/default/include/core-impl/Config.h
+++ b/audio/aidl/default/include/core-impl/Config.h
@@ -20,6 +20,8 @@
namespace aidl::android::hardware::audio::core {
-class Config : public BnConfig {};
+class Config : public BnConfig {
+ ndk::ScopedAStatus getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) override;
+};
} // namespace aidl::android::hardware::audio::core
diff --git a/automotive/remoteaccess/impl/default/client/Android.bp b/automotive/remoteaccess/hal/default/Android.bp
similarity index 64%
rename from automotive/remoteaccess/impl/default/client/Android.bp
rename to automotive/remoteaccess/hal/default/Android.bp
index 6327637..a2bf86c 100644
--- a/automotive/remoteaccess/impl/default/client/Android.bp
+++ b/automotive/remoteaccess/hal/default/Android.bp
@@ -29,28 +29,61 @@
"RemoteAccessService",
],
shared_libs: [
+ "libbase",
"libbinder_ndk",
"liblog",
"libutils",
"libgrpc++",
"libprotobuf-cpp-full",
],
+ defaults: [
+ "vhalclient_defaults",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
+ ],
+}
+
+cc_library {
+ name: "RemoteAccessService",
+ vendor_available: true,
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ srcs: [
+ "src/RemoteAccessService.cpp",
+ ],
+ 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++",
+ "libprotobuf-cpp-full",
+ ],
cflags: [
"-Wno-unused-parameter",
],
}
-cc_library {
- name: "RemoteAccessService",
- vendor: true,
- local_include_dirs: ["include"],
- export_include_dirs: ["include"],
- srcs: [
- "src/RemoteAccessService.cpp",
- ],
+cc_fuzz {
+ name: "android.hardware.automotive.remoteaccess@V1-default-service.aidl_fuzzer",
+ srcs: ["fuzzer/fuzzer.cpp"],
whole_static_libs: [
- "android.hardware.automotive.remoteaccess-V1-ndk",
- "wakeup_client_protos",
+ "RemoteAccessService",
+ ],
+ static_libs: [
+ "libgtest",
+ "libgmock",
],
shared_libs: [
"libbase",
@@ -60,7 +93,17 @@
"libgrpc++",
"libprotobuf-cpp-full",
],
+ defaults: [
+ "vhalclient_defaults",
+ "service_fuzzer_defaults",
+ ],
cflags: [
"-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
],
+ fuzz_config: {
+ cc: [
+ "shanyu@google.com",
+ ],
+ },
}
diff --git a/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
new file mode 100644
index 0000000..292c80e
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.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 <RemoteAccessService.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <gmock/gmock.h>
+#include <grpcpp/test/mock_stream.h>
+#include <wakeup_client.grpc.pb.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+using ::grpc::ClientAsyncReaderInterface;
+using ::grpc::ClientAsyncResponseReaderInterface;
+using ::grpc::ClientContext;
+using ::grpc::ClientReader;
+using ::grpc::ClientReaderInterface;
+using ::grpc::CompletionQueue;
+using ::grpc::Status;
+using ::grpc::testing::MockClientReader;
+using ::testing::_;
+using ::testing::Return;
+
+class MockGrpcClientStub : public WakeupClient::StubInterface {
+ public:
+ ClientReaderInterface<GetRemoteTasksResponse>* GetRemoteTasksRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request) override {
+ MockClientReader<GetRemoteTasksResponse>* mockClientReader =
+ new MockClientReader<GetRemoteTasksResponse>();
+ ON_CALL(*mockClientReader, Finish()).WillByDefault(Return(Status::OK));
+ ON_CALL(*mockClientReader, Read(_)).WillByDefault(Return(false));
+ return mockClientReader;
+ }
+
+ Status NotifyWakeupRequired([[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const NotifyWakeupRequiredRequest& request,
+ [[maybe_unused]] NotifyWakeupRequiredResponse* response) {
+ return Status::OK;
+ }
+
+ // Async methods which we do not care.
+ ClientAsyncReaderInterface<GetRemoteTasksResponse>* AsyncGetRemoteTasksRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request,
+ [[maybe_unused]] CompletionQueue* cq, [[maybe_unused]] void* tag) {
+ return nullptr;
+ }
+
+ ClientAsyncReaderInterface<GetRemoteTasksResponse>* PrepareAsyncGetRemoteTasksRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request,
+ [[maybe_unused]] CompletionQueue* cq) {
+ return nullptr;
+ }
+
+ ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>* AsyncNotifyWakeupRequiredRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const NotifyWakeupRequiredRequest& request,
+ [[maybe_unused]] CompletionQueue* cq) {
+ return nullptr;
+ }
+
+ ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>*
+ PrepareAsyncNotifyWakeupRequiredRaw([[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const NotifyWakeupRequiredRequest& request,
+ [[maybe_unused]] CompletionQueue* c) {
+ return nullptr;
+ }
+};
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ android::hardware::automotive::remoteaccess::MockGrpcClientStub stub;
+ std::shared_ptr<android::hardware::automotive::remoteaccess::RemoteAccessService> service =
+ ndk::SharedRefBase::make<
+ android::hardware::automotive::remoteaccess::RemoteAccessService>(&stub);
+ android::fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
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 83%
rename from automotive/remoteaccess/impl/default/proto/Android.bp
rename to automotive/remoteaccess/hal/default/proto/Android.bp
index d3c75a6..3e0dba1 100644
--- a/automotive/remoteaccess/impl/default/proto/Android.bp
+++ b/automotive/remoteaccess/hal/default/proto/Android.bp
@@ -12,6 +12,15 @@
// 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"],
+}
+
genrule {
name: "wakeup_client_pb_h",
tools: [
@@ -26,7 +35,6 @@
"wakeup_client.pb.h",
"wakeup_client.grpc.pb.h",
],
- vendor: true,
}
genrule {
@@ -43,12 +51,11 @@
"wakeup_client.pb.cc",
"wakeup_client.grpc.pb.cc",
],
- vendor: true,
}
cc_library_static {
name: "wakeup_client_protos",
- vendor: true,
+ vendor_available: true,
host_supported: true,
include_dirs: [
"external/protobuf/src",
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..5cd58d3
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
@@ -0,0 +1,355 @@
+/*
+ * 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) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ 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);
+#else
+ // Don't use VHAL client in fuzzing since IPC is not allowed.
+ return ScopedAStatus::ok();
+#endif
+}
+
+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/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 68a1f26..651c9dc 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -56,43 +56,58 @@
return;
}
- if (FingerprintHalProperties::operation_enroll_fails().value_or(false)) {
- LOG(ERROR) << "Fail: operation_enroll_fails";
- cb->onError(Error::VENDOR, 0 /* vendorError */);
+ // Force error-out
+ auto err = FingerprintHalProperties::operation_enroll_error().value_or(0);
+ if (err != 0) {
+ LOG(ERROR) << "Fail: operation_enroll_error";
+ auto ec = convertError(err);
+ cb->onError(ec.first, ec.second);
return;
}
- // format is "<id>:<progress_ms>,<progress_ms>,...:<result>
+ // Format is "<id>:<progress_ms-[acquiredInfo..]>,...:<result>
auto nextEnroll = FingerprintHalProperties::next_enrollment().value_or("");
auto parts = Util::split(nextEnroll, ":");
if (parts.size() != 3) {
- LOG(ERROR) << "Fail: invalid next_enrollment";
+ LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
cb->onError(Error::VENDOR, 0 /* vendorError */);
return;
}
auto enrollmentId = std::stoi(parts[0]);
- auto progress = Util::split(parts[1], ",");
- for (size_t i = 0; i < progress.size(); i++) {
- auto left = progress.size() - i - 1;
- SLEEP_MS(std::stoi(progress[i]));
+ auto progress = parseEnrollmentCapture(parts[1]);
+ for (size_t i = 0; i < progress.size(); i += 2) {
+ auto left = (progress.size() - i) / 2 - 1;
+ auto duration = progress[i][0];
+ auto acquired = progress[i + 1];
+ auto N = acquired.size();
- if (shouldCancel(cancel)) {
- LOG(ERROR) << "Fail: cancel";
- cb->onError(Error::CANCELED, 0 /* vendorCode */);
- return;
+ for (int j = 0; j < N; j++) {
+ SLEEP_MS(duration / N);
+
+ if (shouldCancel(cancel)) {
+ LOG(ERROR) << "Fail: cancel";
+ cb->onError(Error::CANCELED, 0 /* vendorCode */);
+ return;
+ }
+ auto ac = convertAcquiredInfo(acquired[j]);
+ cb->onAcquired(ac.first, ac.second);
}
- cb->onAcquired(AcquiredInfo::GOOD, 0 /* vendorCode */);
if (left == 0 && !IS_TRUE(parts[2])) { // end and failed
LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
FingerprintHalProperties::next_enrollment({});
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
} else { // progress and update props if last time
+ LOG(INFO) << "onEnroll: " << enrollmentId << " left: " << left;
if (left == 0) {
auto enrollments = FingerprintHalProperties::enrollments();
enrollments.emplace_back(enrollmentId);
FingerprintHalProperties::enrollments(enrollments);
FingerprintHalProperties::next_enrollment({});
+ // change authenticatorId after new enrollment
+ auto id = FingerprintHalProperties::authenticator_id().value_or(0);
+ auto newId = id + 1;
+ FingerprintHalProperties::authenticator_id(newId);
LOG(INFO) << "Enrolled: " << enrollmentId;
}
cb->onEnrollmentProgress(enrollmentId, left);
@@ -104,12 +119,31 @@
const std::future<void>& cancel) {
BEGIN_OP(FingerprintHalProperties::operation_authenticate_latency().value_or(DEFAULT_LATENCY));
- auto now = Util::getSystemNanoTime();
- int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(0);
+ int64_t now = Util::getSystemNanoTime();
+ int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(10);
+ auto acquired = FingerprintHalProperties::operation_authenticate_acquired().value_or("1");
+ auto acquiredInfos = parseIntSequence(acquired);
+ int N = acquiredInfos.size();
+
+ if (N == 0) {
+ LOG(ERROR) << "Fail to parse authentiate acquired info: " + acquired;
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+ return;
+ }
+
+ int i = 0;
do {
if (FingerprintHalProperties::operation_authenticate_fails().value_or(false)) {
LOG(ERROR) << "Fail: operation_authenticate_fails";
- cb->onError(Error::VENDOR, 0 /* vendorError */);
+ cb->onAuthenticationFailed();
+ return;
+ }
+
+ auto err = FingerprintHalProperties::operation_authenticate_error().value_or(0);
+ if (err != 0) {
+ LOG(ERROR) << "Fail: operation_authenticate_error";
+ auto ec = convertError(err);
+ cb->onError(ec.first, ec.second);
return;
}
@@ -126,20 +160,25 @@
return;
}
- auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
- auto enrolls = FingerprintHalProperties::enrollments();
- auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
- if (id > 0 && isEnrolled) {
- cb->onAuthenticationSucceeded(id, {} /* hat */);
- return;
+ if (i < N) {
+ auto ac = convertAcquiredInfo(acquiredInfos[i]);
+ cb->onAcquired(ac.first, ac.second);
+ i++;
}
- SLEEP_MS(100);
+ SLEEP_MS(duration / N);
} while (!Util::hasElapsed(now, duration));
- LOG(ERROR) << "Fail: not enrolled";
- cb->onAuthenticationFailed();
- cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+ auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
+ auto enrolls = FingerprintHalProperties::enrollments();
+ auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
+ if (id > 0 && isEnrolled) {
+ cb->onAuthenticationSucceeded(id, {} /* hat */);
+ return;
+ } else {
+ LOG(ERROR) << "Fail: fingerprint not enrolled";
+ cb->onAuthenticationFailed();
+ }
}
void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb,
@@ -147,17 +186,42 @@
BEGIN_OP(FingerprintHalProperties::operation_detect_interaction_latency().value_or(
DEFAULT_LATENCY));
- if (FingerprintHalProperties::operation_detect_interaction_fails().value_or(false)) {
- LOG(ERROR) << "Fail: operation_detect_interaction_fails";
- cb->onError(Error::VENDOR, 0 /* vendorError */);
+ int64_t duration =
+ FingerprintHalProperties::operation_detect_interaction_duration().value_or(10);
+ auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1");
+ auto acquiredInfos = parseIntSequence(acquired);
+ int N = acquiredInfos.size();
+ int64_t now = Util::getSystemNanoTime();
+
+ if (N == 0) {
+ LOG(ERROR) << "Fail to parse detect interaction acquired info: " + acquired;
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
return;
}
- if (shouldCancel(cancel)) {
- LOG(ERROR) << "Fail: cancel";
- cb->onError(Error::CANCELED, 0 /* vendorCode */);
- return;
- }
+ int i = 0;
+ do {
+ auto err = FingerprintHalProperties::operation_detect_interaction_error().value_or(0);
+ if (err != 0) {
+ LOG(ERROR) << "Fail: operation_detect_interaction_error";
+ auto ec = convertError(err);
+ cb->onError(ec.first, ec.second);
+ return;
+ }
+
+ if (shouldCancel(cancel)) {
+ LOG(ERROR) << "Fail: cancel";
+ cb->onError(Error::CANCELED, 0 /* vendorCode */);
+ return;
+ }
+
+ if (i < N) {
+ auto ac = convertAcquiredInfo(acquiredInfos[i]);
+ cb->onAcquired(ac.first, ac.second);
+ i++;
+ }
+ SLEEP_MS(duration / N);
+ } while (!Util::hasElapsed(now, duration));
auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
auto enrolls = FingerprintHalProperties::enrollments();
@@ -211,24 +275,37 @@
void FakeFingerprintEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
BEGIN_OP(0);
- int64_t authenticatorId = FingerprintHalProperties::authenticator_id().value_or(0);
- if (FingerprintHalProperties::enrollments().size() > 0 && authenticatorId == 0) {
- authenticatorId = 99999999; // default authenticatorId, TODO(b/230515082)
+ int64_t authenticatorId;
+ if (FingerprintHalProperties::enrollments().size() == 0) {
+ authenticatorId = 0;
+ } else {
+ authenticatorId = FingerprintHalProperties::authenticator_id().value_or(0);
+ if (authenticatorId == 0) authenticatorId = 1;
}
cb->onAuthenticatorIdRetrieved(authenticatorId);
}
void FakeFingerprintEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
BEGIN_OP(0);
- auto id = FingerprintHalProperties::authenticator_id().value_or(0);
- auto newId = id + 1;
+ int64_t newId;
+ if (FingerprintHalProperties::enrollments().size() == 0) {
+ newId = 0;
+ } else {
+ auto id = FingerprintHalProperties::authenticator_id().value_or(0);
+ newId = id + 1;
+ }
FingerprintHalProperties::authenticator_id(newId);
cb->onAuthenticatorIdInvalidated(newId);
}
void FakeFingerprintEngine::resetLockoutImpl(ISessionCallback* cb,
- const keymaster::HardwareAuthToken& /*hat*/) {
+ const keymaster::HardwareAuthToken& hat) {
BEGIN_OP(0);
+ if (hat.mac.empty()) {
+ LOG(ERROR) << "Fail: hat in resetLockout()";
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+ return;
+ }
FingerprintHalProperties::lockout(false);
cb->onLockoutCleared();
}
@@ -286,4 +363,96 @@
return {0 /* displayId (not used) */, 0 /* sensorLocationX */, 0 /* sensorLocationY */,
0 /* sensorRadius */, "" /* display */};
}
+
+std::vector<int32_t> FakeFingerprintEngine::parseIntSequence(const std::string& str,
+ const std::string& sep) {
+ std::vector<std::string> seqs = Util::split(str, sep);
+ std::vector<int32_t> res;
+
+ for (const auto& seq : seqs) {
+ int32_t val;
+ if (ParseInt(seq, &val)) {
+ res.push_back(val);
+ } else {
+ LOG(WARNING) << "Invalid int sequence:" + str;
+ res.clear();
+ break;
+ }
+ }
+
+ return res;
+}
+
+std::vector<std::vector<int32_t>> FakeFingerprintEngine::parseEnrollmentCapture(
+ const std::string& str) {
+ std::vector<int32_t> defaultAcquiredInfo = {(int32_t)AcquiredInfo::GOOD};
+ std::vector<std::vector<int32_t>> res;
+ int i = 0, N = str.length();
+ std::size_t found = 0;
+ bool aborted = true;
+
+ while (found != std::string::npos) {
+ std::string durationStr, acquiredStr;
+ found = str.find_first_of("-,", i);
+ if (found == std::string::npos) {
+ if (N - i < 1) break;
+ durationStr = str.substr(i, N - i);
+ } else {
+ durationStr = str.substr(i, found - i);
+ if (str[found] == '-') {
+ found = str.find_first_of('[', found + 1);
+ if (found == std::string::npos) break;
+ i = found + 1;
+ found = str.find_first_of(']', found + 1);
+ if (found == std::string::npos) break;
+ acquiredStr = str.substr(i, found - i);
+ found = str.find_first_of(',', found + 1);
+ }
+ }
+ std::vector<int32_t> duration{0};
+ if (!ParseInt(durationStr, &duration[0])) break;
+ res.push_back(duration);
+ if (!acquiredStr.empty()) {
+ std::vector<int32_t> acquiredInfo = parseIntSequence(acquiredStr);
+ if (acquiredInfo.empty()) break;
+ res.push_back(acquiredInfo);
+ } else
+ res.push_back(defaultAcquiredInfo);
+
+ i = found + 1;
+ if (found == std::string::npos || found == N - 1) aborted = false;
+ }
+
+ if (aborted) {
+ LOG(ERROR) << "Failed to parse enrollment captures:" + str;
+ res.clear();
+ }
+
+ return res;
+}
+
+std::pair<AcquiredInfo, int32_t> FakeFingerprintEngine::convertAcquiredInfo(int32_t code) {
+ std::pair<AcquiredInfo, int32_t> res;
+ if (code > FINGERPRINT_ACQUIRED_VENDOR_BASE) {
+ res.first = AcquiredInfo::VENDOR;
+ res.second = code - FINGERPRINT_ACQUIRED_VENDOR_BASE;
+ } else {
+ res.first = (AcquiredInfo)code;
+ res.second = 0;
+ }
+ return res;
+}
+
+std::pair<Error, int32_t> FakeFingerprintEngine::convertError(int32_t code) {
+ std::pair<Error, int32_t> res;
+ if (code > FINGERPRINT_ERROR_VENDOR_BASE) {
+ res.first = Error::VENDOR;
+ res.second = code - FINGERPRINT_ERROR_VENDOR_BASE;
+ } else {
+ res.first = (Error)code;
+ res.second = 0;
+ }
+ return res;
+}
+
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index 922781c..74e7caf 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -65,8 +65,18 @@
{SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */,
"" /* serialNumber */, SW_VERSION}};
- common::CommonProps commonProps = {SENSOR_ID, SENSOR_STRENGTH, MAX_ENROLLMENTS_PER_USER,
- componentInfo};
+ auto sensorId = FingerprintHalProperties::sensor_id().value_or(SENSOR_ID);
+ auto sensorStrength =
+ FingerprintHalProperties::sensor_strength().value_or((int)SENSOR_STRENGTH);
+ auto maxEnrollments =
+ FingerprintHalProperties::max_enrollments().value_or(MAX_ENROLLMENTS_PER_USER);
+ auto navigationGuesture = FingerprintHalProperties::navigation_guesture().value_or(false);
+ auto detectInteraction = FingerprintHalProperties::detect_interaction().value_or(false);
+ auto displayTouch = FingerprintHalProperties::display_touch().value_or(true);
+ auto controlIllumination = FingerprintHalProperties::control_illumination().value_or(false);
+
+ common::CommonProps commonProps = {sensorId, (common::SensorStrength)sensorStrength,
+ maxEnrollments, componentInfo};
SensorLocation sensorLocation = mEngine->getSensorLocation();
@@ -75,8 +85,10 @@
*out = {{commonProps,
mSensorType,
{sensorLocation},
- SUPPORTS_NAVIGATION_GESTURES,
- false /* supportsDetectInteraction */}};
+ navigationGuesture,
+ detectInteraction,
+ displayTouch,
+ controlIllumination}};
return ndk::ScopedAStatus::ok();
}
diff --git a/biometrics/fingerprint/aidl/default/README.md b/biometrics/fingerprint/aidl/default/README.md
index bb6bb48..ad471f7 100644
--- a/biometrics/fingerprint/aidl/default/README.md
+++ b/biometrics/fingerprint/aidl/default/README.md
@@ -65,7 +65,7 @@
$ adb shell getprop persist.vendor.fingerprint.virtual.enrollments
```
-### Authenticate
+## Authenticate
To authenticate successfully set the enrolled id that should succeed. Unset it
or change the value to make authenticate operations fail:
@@ -74,7 +74,52 @@
$ adb shell setprop vendor.fingerprint.virtual.enrollment_hit 1
````
-### View HAL State
+## Acquired Info Insertion
+
+Fingerprint image acquisition states at HAL are reported to framework via onAcquired() callback. The valid acquired state info for AIDL HAL include
+
+{UNKNOWN(0), GOOD(1), PARTIAL(2), INSUFFICIENT(3), SENSOR_DIRTY(4), TOO_SLOW(5), TOO_FAST(6), VENDOR(7), START(8), TOO_DARK(9), TOO_BRIGHT(10), IMMOBILE(11), RETRYING_CAPTURE(12)}
+
+Refer to [AcquiredInfo.aidl](../android/hardware/biometrics/fingerprint/AcquiredInfo.aidl) for details
+
+
+The states can be specified in sequence for the HAL operations involving fingerprint image captures, namely authenticate, enrollment and detectInteraction
+
+```shell
+$ adb shell setprop vendor.fingerprint.virtual.operation_authenticate_acquired 6,9,1
+$ adb shell setprop vendor.fingerprint.virtual.operation_detect_interaction_acquired 6,1
+$ adb shell setprop vendor.fingerprint.virtual.next_enrollment 2:1000-[5,1],500:true
+
+#next_enrollment format example:
+.---------------------- enrollment id (2)
+| .------------------ the image capture 1 duration (1000ms)
+| | .-------------- acquired info first (TOO_SLOW)
+| | | .------------ acquired info second (GOOD)
+| | | | .-------- the image capture 2 duration (500ms)
+| | | | | .---- enrollment end status (success)
+| | | | | |
+| | | | | |
+| | | | | |
+2:1000-[5,1],500:true
+```
+For vendor specific acquired info, acquiredInfo = 1000 + vendorAcquiredInfo
+
+## Error Insertion
+The valid error codes for AIDL HAL include
+
+{UNKNOWN(0), HW_UNAVAILABLE(1), UNABLE_TO_PROCESS(2), TIMEOUT(3), NO_SPACE(4), CANCELED(5), UNABLE_TO_REMOVE(6), VENDOR(7), BAD_CALIBRATION(8)}
+
+Refer to [Error.aidl](../android/hardware/biometrics/fingerprint/Error.aidl) for details
+
+
+There are many HAL operations which can result in errors, refer to [here](fingerprint.sysprop) file for details.
+
+```shell
+$ adb shell setprop vendor.fingerprint.virtual.operation_authenticate_error 8
+```
+For vendor specific error, errorCode = 1000 + vendorErrorCode
+
+## View HAL State
To view all the properties of the HAL (see `fingerprint.sysprop` file for the API):
diff --git a/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt b/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
index 9dfb74d..fa21663 100644
--- a/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
+++ b/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
@@ -5,7 +5,7 @@
api_name: "authenticator_id"
type: Long
access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.authenticator_id"
+ prop_name: "persist.vendor.fingerprint.virtual.authenticator_id"
}
prop {
api_name: "challenge"
@@ -14,6 +14,21 @@
prop_name: "vendor.fingerprint.virtual.challenge"
}
prop {
+ api_name: "control_illumination"
+ access: ReadWrite
+ prop_name: "persist.vendor.fingerprint.virtual.udfps.control_illumination"
+ }
+ prop {
+ api_name: "detect_interaction"
+ access: ReadWrite
+ prop_name: "persist.vendor.fingerprint.virtual.detect_interaction"
+ }
+ prop {
+ api_name: "display_touch"
+ access: ReadWrite
+ prop_name: "persist.vendor.fingerprint.virtual.udfps.display_touch"
+ }
+ prop {
api_name: "enrollment_hit"
type: Integer
access: ReadWrite
@@ -28,7 +43,18 @@
prop {
api_name: "lockout"
access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.lockout"
+ prop_name: "persist.vendor.fingerprint.virtual.lockout"
+ }
+ prop {
+ api_name: "max_enrollments"
+ type: Integer
+ access: ReadWrite
+ prop_name: "persist.vendor.fingerprint.virtual.max_enrollments"
+ }
+ prop {
+ api_name: "navigation_guesture"
+ access: ReadWrite
+ prop_name: "persist.vendor.fingerprint.virtual.navigation_guesture"
}
prop {
api_name: "next_enrollment"
@@ -37,12 +63,24 @@
prop_name: "vendor.fingerprint.virtual.next_enrollment"
}
prop {
+ api_name: "operation_authenticate_acquired"
+ type: String
+ access: ReadWrite
+ prop_name: "vendor.fingerprint.virtual.operation_authenticate_acquired"
+ }
+ prop {
api_name: "operation_authenticate_duration"
type: Integer
access: ReadWrite
prop_name: "vendor.fingerprint.virtual.operation_authenticate_duration"
}
prop {
+ api_name: "operation_authenticate_error"
+ type: Integer
+ access: ReadWrite
+ prop_name: "vendor.fingerprint.virtual.operation_authenticate_error"
+ }
+ prop {
api_name: "operation_authenticate_fails"
access: ReadWrite
prop_name: "vendor.fingerprint.virtual.operation_authenticate_fails"
@@ -54,9 +92,22 @@
prop_name: "vendor.fingerprint.virtual.operation_authenticate_latency"
}
prop {
- api_name: "operation_detect_interaction_fails"
+ api_name: "operation_detect_interaction_acquired"
+ type: String
access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_fails"
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_acquired"
+ }
+ prop {
+ api_name: "operation_detect_interaction_duration"
+ type: Integer
+ access: ReadWrite
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_duration"
+ }
+ prop {
+ api_name: "operation_detect_interaction_error"
+ type: Integer
+ access: ReadWrite
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_error"
}
prop {
api_name: "operation_detect_interaction_latency"
@@ -65,9 +116,10 @@
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_latency"
}
prop {
- api_name: "operation_enroll_fails"
+ api_name: "operation_enroll_error"
+ type: Integer
access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_enroll_fails"
+ prop_name: "vendor.fingerprint.virtual.operation_enroll_error"
}
prop {
api_name: "operation_enroll_latency"
@@ -76,12 +128,24 @@
prop_name: "vendor.fingerprint.virtual.operation_enroll_latency"
}
prop {
+ api_name: "sensor_id"
+ type: Integer
+ access: ReadWrite
+ prop_name: "persist.vendor.fingerprint.virtual.sensor_id"
+ }
+ prop {
api_name: "sensor_location"
type: String
access: ReadWrite
prop_name: "persist.vendor.fingerprint.virtual.sensor_location"
}
prop {
+ api_name: "sensor_strength"
+ type: Integer
+ access: ReadWrite
+ prop_name: "persist.vendor.fingerprint.virtual.sensor_strength"
+ }
+ prop {
api_name: "type"
type: String
access: ReadWrite
diff --git a/biometrics/fingerprint/aidl/default/fingerprint.sysprop b/biometrics/fingerprint/aidl/default/fingerprint.sysprop
index 85e93b0..9b8fada 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint.sysprop
+++ b/biometrics/fingerprint/aidl/default/fingerprint.sysprop
@@ -32,8 +32,12 @@
api_name: "enrollment_hit"
}
-# the next enrollment in the format: "<id>:<delay>,<delay>,...:<result>"
-# for example: "2:0:true"
+# the next enrollment in the format of:
+# "<id>:<delay>,<delay>,...:<result>"
+# <delay> = <duration-[acquiredInfos]>
+# [acquiredInfos] = [acquiredInfo1, acquiredInfo2, ...]
+# (refer to README.md file for acquiredInfo values)
+# e.g. "2:100,20:true", "2:100-[5,1],20:true"
# this property is reset after enroll completes
prop {
prop_name: "vendor.fingerprint.virtual.next_enrollment"
@@ -45,7 +49,7 @@
# value for getAuthenticatorId or 0
prop {
- prop_name: "vendor.fingerprint.virtual.authenticator_id"
+ prop_name: "persist.vendor.fingerprint.virtual.authenticator_id"
type: Long
scope: Public
access: ReadWrite
@@ -63,7 +67,7 @@
# if locked out
prop {
- prop_name: "vendor.fingerprint.virtual.lockout"
+ prop_name: "persist.vendor.fingerprint.virtual.lockout"
type: Boolean
scope: Public
access: ReadWrite
@@ -79,22 +83,26 @@
api_name: "operation_authenticate_fails"
}
-# force all detectInteraction operations to fail
+# force all detectInteraction operations to error out
+# error consists of errorCode and vendorErrorCode
+# valid errorCodes are listed in README.md file
+# vendorErrorCode = (error>1000) ? error-1000 : 0
+# e.g. error(1002) --> errorCode(7) and vendorErrorCode(2)
prop {
- prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_fails"
- type: Boolean
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_error"
+ type: Integer
scope: Public
access: ReadWrite
- api_name: "operation_detect_interaction_fails"
+ api_name: "operation_detect_interaction_error"
}
-# force all enroll operations to fail
+# force all enroll operations to result in error
prop {
- prop_name: "vendor.fingerprint.virtual.operation_enroll_fails"
- type: Boolean
+ prop_name: "vendor.fingerprint.virtual.operation_enroll_error"
+ type: Integer
scope: Public
access: ReadWrite
- api_name: "operation_enroll_fails"
+ api_name: "operation_enroll_error"
}
# add a latency to authentication operations
@@ -134,6 +142,15 @@
api_name: "operation_authenticate_duration"
}
+# insert error for authenticate operations
+prop {
+ prop_name: "vendor.fingerprint.virtual.operation_authenticate_error"
+ type: Integer
+ scope: Public
+ access: ReadWrite
+ api_name: "operation_authenticate_error"
+}
+
# sensor location
# <x>:<y>:<radius> in pixel
prop {
@@ -143,3 +160,99 @@
access: ReadWrite
api_name: "sensor_location"
}
+
+# acquired info during authentication in format of sequence
+prop {
+ prop_name: "vendor.fingerprint.virtual.operation_authenticate_acquired"
+ type: String
+ scope: Public
+ access: ReadWrite
+ api_name: "operation_authenticate_acquired"
+}
+
+# millisecond duration for detect interaction operations
+# (waits for changes to enrollment_hit)
+prop {
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_duration"
+ type: Integer
+ scope: Public
+ access: ReadWrite
+ api_name: "operation_detect_interaction_duration"
+}
+
+# acquired info during detect interaction operation in format of sequence
+# e.g. 5,6,1 (TOO_SLOW, TOO_FAST, GOOD)
+# onAcquired() callback will be invoked in sequence
+# vendorAcquiredCode = (acquired>1000) ? acquired-1000 : 0
+prop {
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_acquired"
+ type: String
+ scope: Public
+ access: ReadWrite
+ api_name: "operation_detect_interaction_acquired"
+}
+
+# sensor id (default: 5)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.sensor_id"
+ type: Integer
+ scope: Public
+ access: ReadWrite
+ api_name: "sensor_id"
+}
+
+# sensor strength (default: 2)
+# [0=CONVENECE, 1=WEAK, 2=STRONG]
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.sensor_strength"
+ type: Integer
+ scope: Public
+ access: ReadWrite
+ api_name: "sensor_strength"
+}
+
+# max enrollments per user (default: 5)
+#
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.max_enrollments"
+ type: Integer
+ scope: Public
+ access: ReadWrite
+ api_name: "max_enrollments"
+}
+
+# whether support navigation guestures (default: false)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.navigation_guesture"
+ type: Boolean
+ scope: Public
+ access: ReadWrite
+ api_name: "navigation_guesture"
+}
+
+# whether support detect interaction (default: false)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.detect_interaction"
+ type: Boolean
+ scope: Public
+ access: ReadWrite
+ api_name: "detect_interaction"
+}
+
+# whether support display touch by hal (default: true)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.udfps.display_touch"
+ type: Boolean
+ scope: Public
+ access: ReadWrite
+ api_name: "display_touch"
+}
+
+# whether support illumination control by hal (default: false)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.udfps.control_illumination"
+ type: Boolean
+ scope: Public
+ access: ReadWrite
+ api_name: "control_illumination"
+}
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index d7df818..22b1744 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -59,7 +59,17 @@
virtual SensorLocation defaultSensorLocation();
+ std::vector<int32_t> parseIntSequence(const std::string& str, const std::string& sep = ",");
+
+ std::vector<std::vector<int32_t>> parseEnrollmentCapture(const std::string& str);
+
std::mt19937 mRandom;
+
+ private:
+ static constexpr int32_t FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
+ static constexpr int32_t FINGERPRINT_ERROR_VENDOR_BASE = 1000;
+ std::pair<AcquiredInfo, int32_t> convertAcquiredInfo(int32_t code);
+ std::pair<Error, int32_t> convertError(int32_t code);
};
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index 8696d26..32d01f4 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -38,8 +38,9 @@
mLastChallengeRevoked = challenge;
return ndk::ScopedAStatus::ok();
};
- ::ndk::ScopedAStatus onError(fingerprint::Error error, int32_t) override {
+ ::ndk::ScopedAStatus onError(fingerprint::Error error, int32_t vendorCode) override {
mError = error;
+ mErrorVendorCode = vendorCode;
return ndk::ScopedAStatus::ok();
};
::ndk::ScopedAStatus onEnrollmentProgress(int32_t enrollmentId, int32_t remaining) override {
@@ -62,7 +63,10 @@
mInteractionDetectedCount++;
return ndk::ScopedAStatus::ok();
};
- ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
+ ndk::ScopedAStatus onAcquired(AcquiredInfo info, int32_t vendorCode) override {
+ mLastAcquiredInfo = (int32_t)info;
+ mLastAcquiredVendorCode = vendorCode;
+ mLastAcquiredCount++;
return ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus onEnrollmentsEnumerated(
@@ -94,6 +98,7 @@
ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
Error mError = Error::UNKNOWN;
+ int32_t mErrorVendorCode = 0;
int64_t mLastChallenge = -1;
int64_t mLastChallengeRevoked = -1;
int32_t mLastEnrolled = -1;
@@ -105,6 +110,9 @@
bool mAuthenticatorIdInvalidated = false;
bool mLockoutPermanent = false;
int mInteractionDetectedCount = 0;
+ int32_t mLastAcquiredInfo = -1;
+ int32_t mLastAcquiredVendorCode = -1;
+ int32_t mLastAcquiredCount = 0;
};
class FakeFingerprintEngineTest : public ::testing::Test {
@@ -116,6 +124,12 @@
mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
}
+ void TearDown() override {
+ FingerprintHalProperties::operation_authenticate_error(0);
+ FingerprintHalProperties::operation_detect_interaction_error(0);
+ FingerprintHalProperties::operation_authenticate_acquired("");
+ }
+
FakeFingerprintEngine mEngine;
std::shared_ptr<TestSessionCallback> mCallback;
std::promise<void> mCancel;
@@ -135,11 +149,13 @@
TEST_F(FakeFingerprintEngineTest, ResetLockout) {
FingerprintHalProperties::lockout(true);
- mEngine.resetLockoutImpl(mCallback.get(), {});
+ keymaster::HardwareAuthToken hat{.mac = {2, 4}};
+ mEngine.resetLockoutImpl(mCallback.get(), hat);
ASSERT_FALSE(FingerprintHalProperties::lockout().value_or(true));
}
TEST_F(FakeFingerprintEngineTest, AuthenticatorId) {
+ FingerprintHalProperties::enrollments({1});
FingerprintHalProperties::authenticator_id(50);
mEngine.getAuthenticatorIdImpl(mCallback.get());
ASSERT_EQ(50, mCallback->mLastAuthenticatorId);
@@ -162,6 +178,7 @@
ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
ASSERT_EQ(4, mCallback->mLastEnrolled);
+ ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
}
TEST_F(FakeFingerprintEngineTest, EnrollCancel) {
@@ -189,12 +206,28 @@
ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
}
+TEST_F(FakeFingerprintEngineTest, EnrollAcquired) {
+ FingerprintHalProperties::enrollments({});
+ FingerprintHalProperties::next_enrollment("4:0,5-[12,1013]:true");
+ keymaster::HardwareAuthToken hat{.mac = {2, 4}};
+ int32_t prevCnt = mCallback->mLastAcquiredCount;
+ mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
+ ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
+ ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
+ ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
+ ASSERT_EQ(4, mCallback->mLastEnrolled);
+ ASSERT_EQ(prevCnt + 3, mCallback->mLastAcquiredCount);
+ ASSERT_EQ(7, mCallback->mLastAcquiredInfo);
+ ASSERT_EQ(13, mCallback->mLastAcquiredVendorCode);
+}
+
TEST_F(FakeFingerprintEngineTest, Authenticate) {
FingerprintHalProperties::enrollments({1, 2});
FingerprintHalProperties::enrollment_hit(2);
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
ASSERT_FALSE(mCallback->mAuthenticateFailed);
ASSERT_EQ(2, mCallback->mLastAuthenticated);
+ ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
}
TEST_F(FakeFingerprintEngineTest, AuthenticateCancel) {
@@ -211,7 +244,6 @@
FingerprintHalProperties::enrollment_hit({});
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
ASSERT_TRUE(mCallback->mAuthenticateFailed);
- ASSERT_EQ(mCallback->mError, Error::UNABLE_TO_PROCESS);
}
TEST_F(FakeFingerprintEngineTest, AuthenticateNotEnrolled) {
@@ -219,7 +251,6 @@
FingerprintHalProperties::enrollment_hit(3);
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
ASSERT_TRUE(mCallback->mAuthenticateFailed);
- ASSERT_EQ(mCallback->mError, Error::UNABLE_TO_PROCESS);
}
TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) {
@@ -231,11 +262,41 @@
ASSERT_NE(mCallback->mError, Error::UNKNOWN);
}
+TEST_F(FakeFingerprintEngineTest, AuthenticateError8) {
+ FingerprintHalProperties::operation_authenticate_error(8);
+ mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+ ASSERT_EQ(mCallback->mError, (Error)8);
+ ASSERT_EQ(mCallback->mErrorVendorCode, 0);
+}
+
+TEST_F(FakeFingerprintEngineTest, AuthenticateError9) {
+ FingerprintHalProperties::operation_authenticate_error(1009);
+ mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+ ASSERT_EQ(mCallback->mError, (Error)7);
+ ASSERT_EQ(mCallback->mErrorVendorCode, 9);
+}
+
+TEST_F(FakeFingerprintEngineTest, AuthenticateAcquired) {
+ FingerprintHalProperties::lockout(false);
+ FingerprintHalProperties::enrollments({1, 2});
+ FingerprintHalProperties::enrollment_hit(2);
+ FingerprintHalProperties::operation_authenticate_acquired("4,1009");
+ int32_t prevCount = mCallback->mLastAcquiredCount;
+ mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+ ASSERT_FALSE(mCallback->mAuthenticateFailed);
+ ASSERT_EQ(2, mCallback->mLastAuthenticated);
+ ASSERT_EQ(prevCount + 2, mCallback->mLastAcquiredCount);
+ ASSERT_EQ(7, mCallback->mLastAcquiredInfo);
+ ASSERT_EQ(9, mCallback->mLastAcquiredVendorCode);
+}
+
TEST_F(FakeFingerprintEngineTest, InteractionDetect) {
FingerprintHalProperties::enrollments({1, 2});
FingerprintHalProperties::enrollment_hit(2);
+ FingerprintHalProperties::operation_detect_interaction_acquired("");
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
+ ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
}
TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) {
@@ -261,6 +322,26 @@
ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
}
+TEST_F(FakeFingerprintEngineTest, InteractionDetectError) {
+ FingerprintHalProperties::operation_detect_interaction_error(8);
+ mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+ ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
+ ASSERT_EQ(mCallback->mError, (Error)8);
+ ASSERT_EQ(mCallback->mErrorVendorCode, 0);
+}
+
+TEST_F(FakeFingerprintEngineTest, InteractionDetectAcquired) {
+ FingerprintHalProperties::enrollments({1, 2});
+ FingerprintHalProperties::enrollment_hit(2);
+ FingerprintHalProperties::operation_detect_interaction_acquired("4,1013");
+ int32_t prevCount = mCallback->mLastAcquiredCount;
+ mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+ ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
+ ASSERT_EQ(prevCount + 2, mCallback->mLastAcquiredCount);
+ ASSERT_EQ(7, mCallback->mLastAcquiredInfo);
+ ASSERT_EQ(13, mCallback->mLastAcquiredVendorCode);
+}
+
TEST_F(FakeFingerprintEngineTest, EnumerateEnrolled) {
FingerprintHalProperties::enrollments({2, 4, 8});
mEngine.enumerateEnrollmentsImpl(mCallback.get());
@@ -290,6 +371,76 @@
}
}
+TEST_F(FakeFingerprintEngineTest, parseIntSequence) {
+ std::vector<int32_t> seqV;
+ seqV = mEngine.parseIntSequence("");
+ ASSERT_EQ(0, seqV.size());
+ seqV = mEngine.parseIntSequence("2");
+ ASSERT_EQ(1, seqV.size());
+ ASSERT_EQ(2, seqV[0]);
+ seqV = mEngine.parseIntSequence("2,3,4");
+ std::vector<int32_t> expV{2, 3, 4};
+ ASSERT_EQ(expV, seqV);
+ seqV = mEngine.parseIntSequence("2,3,a");
+ ASSERT_EQ(0, seqV.size());
+ seqV = mEngine.parseIntSequence("2, 3, 4");
+ ASSERT_EQ(expV, seqV);
+ seqV = mEngine.parseIntSequence("123,456");
+ ASSERT_EQ(2, seqV.size());
+ std::vector<int32_t> expV1{123, 456};
+ ASSERT_EQ(expV1, seqV);
+ seqV = mEngine.parseIntSequence("12f3,456");
+ ASSERT_EQ(0, seqV.size());
+}
+
+TEST_F(FakeFingerprintEngineTest, parseEnrollmentCaptureOk) {
+ std::vector<std::vector<int32_t>> ecV;
+ ecV = mEngine.parseEnrollmentCapture("100,200,300");
+ ASSERT_EQ(6, ecV.size());
+ std::vector<std::vector<int32_t>> expE{{100}, {200}, {300}};
+ std::vector<int32_t> defC{1};
+ for (int i = 0; i < ecV.size(); i += 2) {
+ ASSERT_EQ(expE[i / 2], ecV[i]);
+ ASSERT_EQ(defC, ecV[i + 1]);
+ }
+ ecV = mEngine.parseEnrollmentCapture("100");
+ ASSERT_EQ(2, ecV.size());
+ ASSERT_EQ(expE[0], ecV[0]);
+ ASSERT_EQ(defC, ecV[1]);
+
+ ecV = mEngine.parseEnrollmentCapture("100-[5,6,7]");
+ std::vector<int32_t> expC{5, 6, 7};
+ ASSERT_EQ(2, ecV.size());
+ for (int i = 0; i < ecV.size(); i += 2) {
+ ASSERT_EQ(expE[i / 2], ecV[i]);
+ ASSERT_EQ(expC, ecV[i + 1]);
+ }
+ ecV = mEngine.parseEnrollmentCapture("100-[5,6,7], 200, 300-[9,10]");
+ std::vector<std::vector<int32_t>> expC1{{5, 6, 7}, {1}, {9, 10}};
+ ASSERT_EQ(6, ecV.size());
+ for (int i = 0; i < ecV.size(); i += 2) {
+ ASSERT_EQ(expE[i / 2], ecV[i]);
+ ASSERT_EQ(expC1[i / 2], ecV[i + 1]);
+ }
+ ecV = mEngine.parseEnrollmentCapture("100-[5,6,7], 200-[2,1], 300-[9]");
+ std::vector<std::vector<int32_t>> expC2{{5, 6, 7}, {2, 1}, {9}};
+ ASSERT_EQ(ecV.size(), 6);
+ for (int i = 0; i < ecV.size(); i += 2) {
+ ASSERT_EQ(expE[i / 2], ecV[i]);
+ ASSERT_EQ(expC2[i / 2], ecV[i + 1]);
+ }
+}
+
+TEST_F(FakeFingerprintEngineTest, parseEnrollmentCaptureFail) {
+ std::vector<std::string> badStr{"10c", "100-5", "100-[5,6,7", "100-5,6,7]",
+ "100,2x0,300", "200-[f]", "a,b"};
+ std::vector<std::vector<int32_t>> ecV;
+ for (const auto s : badStr) {
+ ecV = mEngine.parseEnrollmentCapture(s);
+ ASSERT_EQ(ecV.size(), 0);
+ }
+}
+
} // namespace aidl::android::hardware::biometrics::fingerprint
int main(int argc, char** argv) {
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
index 485f401..7c0021f 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
@@ -47,14 +47,10 @@
sc.sensorRadius == FakeFingerprintEngineUdfps::defaultSensorRadius && sc.display == "");
}
-TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocation) {
- FingerprintHalProperties::sensor_location("");
- SensorLocation sc = mEngine.getSensorLocation();
- ASSERT_TRUE(isDefaultLocation(sc));
-
+TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocationOk) {
auto loc = "100:200:30";
FingerprintHalProperties::sensor_location(loc);
- sc = mEngine.getSensorLocation();
+ SensorLocation sc = mEngine.getSensorLocation();
ASSERT_TRUE(sc.sensorLocationX == 100);
ASSERT_TRUE(sc.sensorLocationY == 200);
ASSERT_TRUE(sc.sensorRadius == 30);
@@ -66,8 +62,14 @@
ASSERT_TRUE(sc.sensorLocationY == 200);
ASSERT_TRUE(sc.sensorRadius == 30);
ASSERT_TRUE(sc.display == "screen1");
+}
- loc = "100";
+TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocationBad) {
+ FingerprintHalProperties::sensor_location("");
+ SensorLocation sc = mEngine.getSensorLocation();
+ ASSERT_TRUE(isDefaultLocation(sc));
+
+ auto loc = "100";
FingerprintHalProperties::sensor_location(loc);
sc = mEngine.getSensorLocation();
ASSERT_TRUE(isDefaultLocation(sc));
diff --git a/broadcastradio/aidl/Android.bp b/broadcastradio/aidl/Android.bp
index 41d637c..2d8078b 100644
--- a/broadcastradio/aidl/Android.bp
+++ b/broadcastradio/aidl/Android.bp
@@ -14,6 +14,15 @@
// 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.broadcastradio",
vendor_available: true,
diff --git a/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl b/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
index e487494..29fec68 100644
--- a/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
@@ -33,8 +33,8 @@
parcelable StreamBuffer {
/**
* The ID of the stream this buffer is associated with. -1 indicates an
- * invalid (empty) StreamBuffer, in which case buffer must also point to
- * null and bufferId must be 0.
+ * invalid (empty) StreamBuffer, in which case buffer must be empty
+ * and bufferId must be 0.
*/
int streamId;
@@ -48,7 +48,7 @@
* corresponding stream is removed from stream configuration or until camera
* device session is closed. After the first time a buffer is introduced to
* HAL, in the future camera service must refer to the same buffer using
- * only bufferId, and keep the buffer handle null.
+ * only bufferId, and keep the buffer handle empty.
*/
long bufferId;
@@ -59,10 +59,10 @@
* is not seen by the HAL before, this buffer handle is guaranteed to be a
* valid handle to a graphics buffer, with dimensions and format matching
* that of the stream. If the bufferId has been sent to the HAL before, this
- * buffer handle must be null and HAL must look up the actual buffer handle
+ * buffer handle must be empty and HAL must look up the actual buffer handle
* to use from its own bufferId to buffer handle map.
*
- * For StreamBuffers returned in a CaptureResult, this must be null, since
+ * For StreamBuffers returned in a CaptureResult, this must be empty, since
* the handle to the buffer is already known to the client (since the client
* sent it in the matching CaptureRequest), and the handle can be identified
* by the combination of frame number and stream ID.
@@ -81,11 +81,11 @@
* The acquire sync fence for this buffer. The HAL must wait on this fence
* fd before attempting to read from or write to this buffer.
*
- * In a buffer included in a CaptureRequest, the client may set this to null
+ * In a buffer included in a CaptureRequest, the client may leave this empty
* to indicate that no waiting is necessary for this buffer.
*
* When the HAL returns an input or output buffer to the framework with
- * processCaptureResult(), the acquireFence must be set to null. If the HAL
+ * processCaptureResult(), the acquireFence must be empty. If the HAL
* never waits on the acquireFence due to an error in filling or reading a
* buffer, when calling processCaptureResult() the HAL must set the
* releaseFence of the buffer to be the acquireFence passed to it by the
@@ -97,17 +97,17 @@
/**
* The release sync fence for this buffer. The HAL must set this to a valid
* fence fd when returning the input buffer or output buffers to the client
- * in a CaptureResult, or set it to null to indicate that no waiting is
+ * in a CaptureResult, or leave it empty to indicate that no waiting is
* required for this buffer.
*
- * The client must set this to be null for all buffers included in a
+ * The client must leave this empty for all buffers included in a
* processCaptureRequest call.
*
* After signaling the releaseFence for this buffer, the HAL
* must not make any further attempts to access this buffer as the
* ownership has been fully transferred back to the client.
*
- * If this is null, then the ownership of this buffer is transferred back
+ * If this is empty, then the ownership of the buffer is transferred back
* immediately upon the call of processCaptureResult.
*/
NativeHandle releaseFence;
diff --git a/common/support/NativeHandle.cpp b/common/support/NativeHandle.cpp
index 321d7a8..126ef2e 100644
--- a/common/support/NativeHandle.cpp
+++ b/common/support/NativeHandle.cpp
@@ -22,6 +22,13 @@
using aidl::android::hardware::common::NativeHandle;
+/**
+ * Checks if a NativeHandle is null
+ */
+bool isAidlNativeHandleEmpty(const NativeHandle& handle) {
+ return handle.fds.empty() && handle.ints.empty();
+}
+
static native_handle_t* fromAidl(const NativeHandle& handle, bool doDup) {
native_handle_t* to = native_handle_create(handle.fds.size(), handle.ints.size());
if (!to) return nullptr;
diff --git a/common/support/include/aidlcommonsupport/NativeHandle.h b/common/support/include/aidlcommonsupport/NativeHandle.h
index 10eecba..b5ea1dd 100644
--- a/common/support/include/aidlcommonsupport/NativeHandle.h
+++ b/common/support/include/aidlcommonsupport/NativeHandle.h
@@ -22,6 +22,11 @@
namespace android {
/**
+ * Checks if a NativeHandle is empty.
+ */
+bool isAidlNativeHandleEmpty(const aidl::android::hardware::common::NativeHandle& handle);
+
+/**
* Creates a libcutils native handle from an AIDL native handle, but it does not
* dup internally, so it will contain the same FDs as the handle itself. The
* result should be deleted with native_handle_delete.
diff --git a/common/support/test.cpp b/common/support/test.cpp
index 2359277..9b79581 100644
--- a/common/support/test.cpp
+++ b/common/support/test.cpp
@@ -62,6 +62,7 @@
TEST(ConvertNativeHandle, MakeFromAidlEmpty) {
NativeHandle handle;
+ EXPECT_TRUE(isAidlNativeHandleEmpty(handle));
native_handle_t* to = makeFromAidl(handle);
checkEq(handle, to, false /*exceptFds*/);
// no native_handle_close b/c fds are owned by NativeHandle
@@ -70,6 +71,7 @@
TEST(ConvertNativeHandle, MakeFromAidl) {
NativeHandle handle = makeTestAidlHandle();
+ EXPECT_FALSE(isAidlNativeHandleEmpty(handle));
native_handle_t* to = makeFromAidl(handle);
checkEq(handle, to, false /*exceptFds*/);
// no native_handle_close b/c fds are owned by NativeHandle
@@ -106,6 +108,7 @@
TEST(ConvertNativeHandle, MakeToAidlEmpty) {
native_handle_t* handle = native_handle_create(0, 0);
NativeHandle to = makeToAidl(handle);
+ EXPECT_TRUE(isAidlNativeHandleEmpty(to));
checkEq(to, handle, false /*exceptFds*/);
// no native_handle_close b/c fds are owned by NativeHandle now
EXPECT_EQ(0, native_handle_delete(handle));
@@ -114,6 +117,7 @@
TEST(ConvertNativeHandle, MakeToAidl) {
native_handle_t* handle = makeTestLibcutilsHandle();
NativeHandle to = makeToAidl(handle);
+ EXPECT_FALSE(isAidlNativeHandleEmpty(to));
checkEq(to, handle, false /*exceptFds*/);
// no native_handle_close b/c fds are owned by NativeHandle now
EXPECT_EQ(0, native_handle_delete(handle));
@@ -122,6 +126,7 @@
TEST(ConvertNativeHandle, DupToAidlEmpty) {
native_handle_t* handle = native_handle_create(0, 0);
NativeHandle to = dupToAidl(handle);
+ EXPECT_TRUE(isAidlNativeHandleEmpty(to));
checkEq(to, handle, true /*exceptFds*/);
EXPECT_EQ(0, native_handle_close(handle));
EXPECT_EQ(0, native_handle_delete(handle));
@@ -130,6 +135,7 @@
TEST(ConvertNativeHandle, DupToAidl) {
native_handle_t* handle = makeTestLibcutilsHandle();
NativeHandle to = dupToAidl(handle);
+ EXPECT_FALSE(isAidlNativeHandleEmpty(to));
checkEq(to, handle, true /*exceptFds*/);
EXPECT_EQ(0, native_handle_close(handle));
EXPECT_EQ(0, native_handle_delete(handle));
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index a20d15d..6fca4f3 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -190,9 +190,9 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="aidl" optional="true">
<name>android.hardware.confirmationui</name>
- <version>1.0</version>
+ <version>1</version>
<interface>
<name>IConfirmationUI</name>
<instance>default</instance>
@@ -461,7 +461,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.radio.data</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IRadioData</name>
<instance>slot1</instance>
@@ -600,9 +600,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/OWNERS b/confirmationui/OWNERS
new file mode 100644
index 0000000..2bcdb0e
--- /dev/null
+++ b/confirmationui/OWNERS
@@ -0,0 +1,2 @@
+swillden@google.com
+subrahmanyaman@google.com
diff --git a/confirmationui/aidl/Android.bp b/confirmationui/aidl/Android.bp
new file mode 100644
index 0000000..4ba4acd
--- /dev/null
+++ b/confirmationui/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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+ name: "android.hardware.confirmationui",
+ vendor_available: true,
+ imports: [
+ "android.hardware.security.keymint-V2",
+ ],
+ srcs: ["android/hardware/confirmationui/*.aidl"],
+ stability: "vintf",
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ ndk: {
+ apps_enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ },
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.aidl
new file mode 100644
index 0000000..6d6ec97
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.confirmationui;
+@VintfStability
+interface IConfirmationResultCallback {
+ void result(in int error, in byte[] formattedMessage, in byte[] confirmationToken);
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl
new file mode 100644
index 0000000..c5c7aa7
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.confirmationui;
+@VintfStability
+interface IConfirmationUI {
+ void abort();
+ void deliverSecureInputEvent(in android.hardware.security.keymint.HardwareAuthToken secureInputToken);
+ void promptUserConfirmation(in android.hardware.confirmationui.IConfirmationResultCallback resultCB, in byte[] promptText, in byte[] extraData, in @utf8InCpp String locale, in android.hardware.confirmationui.UIOption[] uiOptions);
+ const int OK = 0;
+ const int CANCELED = 1;
+ const int ABORTED = 2;
+ const int OPERATION_PENDING = 3;
+ const int IGNORED = 4;
+ const int SYSTEM_ERROR = 5;
+ const int UNIMPLEMENTED = 6;
+ const int UNEXPECTED = 7;
+ const int UI_ERROR = 65536;
+ const int UI_ERROR_MISSING_GLYPH = 65537;
+ const int UI_ERROR_MESSAGE_TOO_LONG = 65538;
+ const int UI_ERROR_MALFORMED_UTF8ENCODING = 65539;
+ const int TEST_KEY_BYTE = 165;
+ const int MAX_MESSAGE_SIZE = 6144;
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl
new file mode 100644
index 0000000..b8629d1
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.confirmationui;
+@Backing(type="int") @VintfStability
+enum TestModeCommands {
+ OK_EVENT = 0,
+ CANCEL_EVENT = 1,
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl
new file mode 100644
index 0000000..ebecf9e
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.confirmationui;
+@Backing(type="int") @VintfStability
+enum UIOption {
+ ACCESSIBILITY_INVERTED = 0,
+ ACCESSIBILITY_MAGNIFIED = 1,
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
new file mode 100644
index 0000000..2165fdd
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
@@ -0,0 +1,66 @@
+/*
+ * 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.confirmationui;
+
+import android.hardware.confirmationui.IConfirmationUI;
+
+/**
+ * Callback interface passed to IConfirmationUI::promptUserConfirmation().
+ * Informs the caller about the result of the prompt operation.
+ */
+@VintfStability
+interface IConfirmationResultCallback {
+ /**
+ * This callback is called by the confirmation provider when it stops prompting the user.
+ * Iff the user has confirmed the prompted text, error is ErrorCode::OK and the
+ * parameters formattedMessage and confirmationToken hold the values needed to request
+ * a signature from keymaster.
+ * In all other cases formattedMessage and confirmationToken must be of length 0.
+ *
+ * @param error - OK: IFF the user has confirmed the prompt.
+ * - CANCELED: If the user has pressed the cancel button.
+ * - ABORTED: If IConfirmationUI::abort() was called.
+ * - SYSTEM_ERROR: If an unexpected System error occurred that prevented the TUI
+ * from being shut down gracefully.
+ *
+ * @param formattedMessage holds the prompt text and extra data.
+ * The message is CBOR (RFC 7049) encoded and has the following format:
+ * CBOR_MAP{ "prompt", <promptText>, "extra", <extraData> }
+ * The message is a CBOR encoded map (type 5) with the keys
+ * "prompt" and "extra". The keys are encoded as CBOR text string
+ * (type 3). The value <promptText> is encoded as CBOR text string
+ * (type 3), and the value <extraData> is encoded as CBOR byte string
+ * (type 2). The map must have exactly one key value pair for each of
+ * the keys "prompt" and "extra". Other keys are not allowed.
+ * The value of "prompt" is given by the proptText argument to
+ * IConfirmationUI::promptUserConfirmation and must not be modified
+ * by the implementation.
+ * The value of "extra" is given by the extraData argument to
+ * IConfirmationUI::promptUserConfirmation and must not be modified
+ * or interpreted by the implementation.
+ *
+ * @param confirmationToken a 32-byte HMAC-SHA256 value, computed over
+ * "confirmation token" || <formattedMessage>
+ * i.e. the literal UTF-8 encoded string "confirmation token", without
+ * the "", concatenated with the formatted message as returned in the
+ * formattedMessage argument. The HMAC is keyed with a 256-bit secret
+ * which is shared with Keymaster. In test mode the test key MUST be
+ * used (see types.hal TestModeCommands and
+ * IConfirmationUI::TEST_KEY_BYTE).
+ */
+ void result(in int error, in byte[] formattedMessage, in byte[] confirmationToken);
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl
new file mode 100644
index 0000000..f071126
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl
@@ -0,0 +1,146 @@
+/*
+ * 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.confirmationui;
+
+import android.hardware.confirmationui.IConfirmationResultCallback;
+import android.hardware.confirmationui.UIOption;
+import android.hardware.security.keymint.HardwareAuthToken;
+
+@VintfStability
+interface IConfirmationUI {
+ // Possible Errors.
+ /**
+ * API call succeeded or the user gave approval (result callback).
+ */
+ const int OK = 0;
+ /**
+ * The user canceled the TUI (result callback).
+ */
+ const int CANCELED = 1;
+ /**
+ * IConfirmationUI::abort() was called. (result callback).
+ */
+ const int ABORTED = 2;
+ /**
+ * Cannot start another prompt.
+ */
+ const int OPERATION_PENDING = 3;
+ /**
+ * IConfirmationUI::deliverSecureInputEvent call was ignored.
+ */
+ const int IGNORED = 4;
+ /**
+ * An unexpected system error occurred.
+ */
+ const int SYSTEM_ERROR = 5;
+ /**
+ * Returned by an unimplemented API call.
+ */
+ const int UNIMPLEMENTED = 6;
+ /**
+ * This is returned when an error is diagnosed that should have been
+ * caught by earlier input sanitization. Should never be seen in production.
+ */
+ const int UNEXPECTED = 7;
+ /**
+ * General UI error.
+ */
+ const int UI_ERROR = 0x10000;
+ /**
+ * This is returned if there is no corresponding glyph for a character.
+ */
+ const int UI_ERROR_MISSING_GLYPH = 0x10001;
+ /**
+ * The implementation must return this error code on promptUserConfirmation if the
+ * resulting formatted message does not fit into MAX_MESSAGE_SIZE bytes. It is
+ * advised that the implementation formats the message upon receiving this API call to
+ * be able to diagnose this syndrome.
+ */
+ const int UI_ERROR_MESSAGE_TOO_LONG = 0x10002;
+ /**
+ * This is returned if the UTF8 encoding is malformed.
+ */
+ const int UI_ERROR_MALFORMED_UTF8ENCODING = 0x10003;
+
+ // Constants
+ /**
+ * The test key is 32byte word with all bytes set to TEST_KEY_BYTE.
+ */
+ const int TEST_KEY_BYTE = 0xA5;
+ /**
+ * This defines the maximum message size. This indirectly limits the size of the prompt text
+ * and the extra data that can be passed to the confirmation UI. The prompt text and extra data
+ * must fit in to this size including CBOR header information.
+ */
+ const int MAX_MESSAGE_SIZE = 0x1800;
+
+ /**
+ * Aborts a pending user prompt. This allows the framework to gracefully end a TUI dialog.
+ * If a TUI operation was pending the corresponding call back is informed with
+ * ErrorCode::Aborted.
+ */
+ void abort();
+
+ /**
+ * DeliverSecureInput is used by the framework to deliver a secure input event to the
+ * confirmation provider.
+ *
+ * VTS test mode:
+ * This function can be used to test certain code paths non-interactively.
+ * See TestModeCommands.aidl for details.
+ *
+ * @param secureInputToken An authentication token as generated by Android authentication
+ * providers.
+ */
+ void deliverSecureInputEvent(in HardwareAuthToken secureInputToken);
+
+ /**
+ * Asynchronously initiates a confirmation UI dialog prompting the user to confirm a given text.
+ * The TUI prompt must be implemented in such a way that a positive response indicates with
+ * high confidence that a user has seen the given prompt text even if the Android framework
+ * including the kernel was compromised.
+ *
+ * Service status return:
+ *
+ * OK IFF the dialog was successfully started. In this case, and only in this
+ * case, the implementation must, eventually, call the callback to
+ * indicate completion.
+ * OPERATION_PENDING is returned when the confirmation provider is currently
+ * in use.
+ * SYSTEM_ERROR an error occurred trying to communicate with the confirmation
+ * provider (e.g. trusted app).
+ * UI_ERROR the confirmation provider encountered an issue with displaying
+ * the prompt text to the user.
+ *
+ * @param resultCB Implementation of IResultCallback. Used by the implementation to report
+ * the result of the current pending user prompt.
+ *
+ * @param promptText UTF-8 encoded bytes which is to be presented to the user.
+ *
+ * @param extraData A binary blob that must be included in the formatted output message as is.
+ * It is opaque to the implementation. Implementations must neither interpret
+ * nor modify the content.
+ *
+ * @param locale String specifying the locale that must be used by the TUI dialog. The string
+ * is an IETF BCP 47 tag.
+ *
+ * @param uiOptions A set of uiOptions manipulating how the confirmation prompt is displayed.
+ * Refer to UIOption in types.hal for possible options.
+ */
+ void promptUserConfirmation(in IConfirmationResultCallback resultCB, in byte[] promptText,
+ in byte[] extraData, in @utf8InCpp String locale, in UIOption[] uiOptions);
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl b/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl
new file mode 100644
index 0000000..5b1d8fb
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl
@@ -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.
+ */
+
+package android.hardware.confirmationui;
+
+/**
+ * Test mode commands.
+ *
+ * IConfirmationUI::deliverSecureInputEvent can be used to test certain code paths.
+ * To that end, the caller passes an auth token that has an HMAC keyed with the test key
+ * (see IConfirmationUI::TEST_KEY_BYTE). Implementations first check the HMAC against test key.
+ * If the test key produces a matching HMAC, the implementation evaluates the challenge field
+ * of the auth token against the values defined in TestModeCommand.
+ * If the command indicates that a confirmation token is to be generated the test key MUST be used
+ * to generate this confirmation token.
+ *
+ * See command code for individual test command descriptions.
+ */
+@VintfStability
+@Backing(type="int")
+enum TestModeCommands {
+ /**
+ * Simulates the user pressing the OK button on the UI. If no operation is pending
+ * ResponseCode::Ignored must be returned. A pending operation is finalized successfully
+ * see IConfirmationResultCallback::result, however, the test key
+ * (see IConfirmationUI::TEST_KEY_BYTE) MUST be used to generate the confirmation token.
+ */
+ OK_EVENT = 0,
+ /**
+ * Simulates the user pressing the CANCEL button on the UI. If no operation is pending
+ * Result::Ignored must be returned. A pending operation is finalized as specified in
+ * IConfirmationResultCallback.hal.
+ */
+ CANCEL_EVENT = 1,
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl b/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl
new file mode 100644
index 0000000..b242c53
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.confirmationui;
+
+/**
+ * UI modification options.
+ */
+@VintfStability
+@Backing(type="int")
+enum UIOption {
+ /**
+ * Accessibility: Requests color inverted style.
+ */
+ ACCESSIBILITY_INVERTED = 0,
+ /**
+ * Accessibility: Requests magnified style.
+ */
+ ACCESSIBILITY_MAGNIFIED = 1,
+}
diff --git a/confirmationui/aidl/vts/functional/Android.bp b/confirmationui/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..3649c87
--- /dev/null
+++ b/confirmationui/aidl/vts/functional/Android.bp
@@ -0,0 +1,45 @@
+//
+// 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
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalConfirmationUITargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "keymint_use_latest_hal_aidl_ndk_shared",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "VtsHalConfirmationUITargetTest.cpp",
+ ],
+ static_libs: [
+ "android.hardware.confirmationui-V1-ndk",
+ "libcn-cbor",
+ "android.hardware.confirmationui-support-lib",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcrypto",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp b/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
new file mode 100644
index 0000000..61dae8b
--- /dev/null
+++ b/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
@@ -0,0 +1,535 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "ConfirmationIOAidlHalTest"
+
+#include <algorithm>
+#include <condition_variable>
+#include <future>
+#include <iostream>
+#include <memory>
+#include <mutex>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/confirmationui/BnConfirmationResultCallback.h>
+#include <aidl/android/hardware/confirmationui/IConfirmationUI.h>
+#include <aidl/android/hardware/confirmationui/TestModeCommands.h>
+#include <aidl/android/hardware/confirmationui/UIOption.h>
+#include <android-base/thread_annotations.h>
+#include <android/hardware/confirmationui/support/confirmationui_utils.h>
+#include <cutils/log.h>
+
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+
+#include <cn-cbor/cn-cbor.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+
+static constexpr int TIMEOUT_PERIOD = 10;
+
+namespace aidl::android::hardware::confirmationui::test {
+using ::aidl::android::hardware::security::keymint::HardwareAuthenticatorType;
+using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
+using ::android::hardware::confirmationui::support::auth_token_key_t;
+using ::android::hardware::confirmationui::support::ByteBufferProxy;
+using ::android::hardware::confirmationui::support::HMac;
+using ::android::hardware::confirmationui::support::hmac_t;
+using ::android::hardware::confirmationui::support::hton;
+using ::android::hardware::confirmationui::support::NullOr;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+
+namespace {
+const auth_token_key_t testKey(static_cast<uint8_t>(IConfirmationUI::TEST_KEY_BYTE));
+
+class HMacImplementation {
+ public:
+ static NullOr<hmac_t> hmac256(const auth_token_key_t& key,
+ std::initializer_list<ByteBufferProxy> buffers) {
+ HMAC_CTX hmacCtx;
+ HMAC_CTX_init(&hmacCtx);
+ if (!HMAC_Init_ex(&hmacCtx, key.data(), key.size(), EVP_sha256(), nullptr)) {
+ return {};
+ }
+ for (auto& buffer : buffers) {
+ if (!HMAC_Update(&hmacCtx, buffer.data(), buffer.size())) {
+ return {};
+ }
+ }
+ hmac_t result;
+ if (!HMAC_Final(&hmacCtx, result.data(), nullptr)) {
+ return {};
+ }
+ return result;
+ }
+};
+
+using HMacer = HMac<HMacImplementation>;
+
+template <typename... Data>
+vector<uint8_t> testHMAC(const Data&... data) {
+ auto hmac = HMacer::hmac256(testKey, data...);
+ if (!hmac.isOk()) {
+ ADD_FAILURE() << "Failed to compute test hmac. This is a self-test error.";
+ return {};
+ }
+ vector<uint8_t> result(hmac.value().size());
+ std::copy(hmac.value().data(), hmac.value().data() + hmac.value().size(), result.data());
+ return result;
+}
+
+template <typename T>
+auto toBytes(const T& v) -> const uint8_t (&)[sizeof(T)] {
+ return *reinterpret_cast<const uint8_t(*)[sizeof(T)]>(&v);
+}
+
+HardwareAuthToken makeTestToken(const TestModeCommands command, uint64_t timestamp = 0) {
+ HardwareAuthToken auth_token;
+ auth_token.challenge = static_cast<uint64_t>(command);
+ auth_token.userId = 0;
+ auth_token.authenticatorId = 0;
+ auth_token.authenticatorType = HardwareAuthenticatorType::NONE;
+ auth_token.timestamp = {static_cast<int64_t>(timestamp)};
+
+ // Canonical form of auth-token v0
+ // version (1 byte)
+ // challenge (8 bytes)
+ // user_id (8 bytes)
+ // authenticator_id (8 bytes)
+ // authenticator_type (4 bytes)
+ // timestamp (8 bytes)
+ // total 37 bytes
+ auth_token.mac = testHMAC("\0",
+ toBytes(auth_token.challenge), //
+ toBytes(auth_token.userId), //
+ toBytes(auth_token.authenticatorId), //
+ toBytes(hton(auth_token.authenticatorType)), //
+ toBytes(hton(auth_token.timestamp))); //
+
+ return auth_token;
+}
+
+#define DEBUG_CONFRIMATIONUI_UTILS_TEST
+
+#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
+std::ostream& hexdump(std::ostream& out, const uint8_t* data, size_t size) {
+ for (size_t i = 0; i < size; ++i) {
+ uint8_t byte = data[i];
+ out << std::hex << std::setw(2) << std::setfill('0') << (unsigned)byte;
+ switch (i & 0xf) {
+ case 0xf:
+ out << "\n";
+ break;
+ case 7:
+ out << " ";
+ break;
+ default:
+ out << " ";
+ break;
+ }
+ }
+ return out;
+}
+#endif
+
+constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9'
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+std::string hex2str(std::string a) {
+ std::string b;
+ size_t num = a.size() / 2;
+ b.resize(num);
+ for (size_t i = 0; i < num; i++) {
+ b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
+ }
+ return b;
+}
+
+int getReturnCode(const ::ndk::ScopedAStatus& result) {
+ if (result.isOk()) return IConfirmationUI::OK;
+
+ if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ return static_cast<int>(result.getServiceSpecificError());
+ }
+ return result.getStatus();
+}
+
+} // namespace
+
+class ConfirmationUIAidlTest : public ::testing::TestWithParam<std::string> {
+ public:
+ void TearDown() override { confirmator_->abort(); }
+ void SetUp() override {
+ std::string name = GetParam();
+ ASSERT_TRUE(AServiceManager_isDeclared(name.c_str())) << name;
+ ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
+ ASSERT_NE(binder, nullptr);
+ confirmator_ = IConfirmationUI::fromBinder(binder);
+ ASSERT_NE(confirmator_, nullptr);
+ }
+
+ // Used as a mechanism to inform the test about data/event callback
+ inline void notify() {
+ std::unique_lock<std::mutex> lock(mtx_);
+ cv_.notify_one();
+ }
+
+ // Test code calls this function to wait for data/event callback
+ inline std::cv_status wait() {
+ std::unique_lock<std::mutex> lock(mtx_);
+ auto now = std::chrono::system_clock::now();
+ std::cv_status status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+ return status;
+ }
+
+ protected:
+ shared_ptr<IConfirmationUI> confirmator_;
+
+ private:
+ // synchronization objects
+ std::mutex mtx_;
+ std::condition_variable cv_;
+};
+
+class ConfirmationTestCallback
+ : public ::aidl::android::hardware::confirmationui::BnConfirmationResultCallback {
+ public:
+ ConfirmationTestCallback(ConfirmationUIAidlTest& parent) : parent_(parent){};
+ virtual ~ConfirmationTestCallback() = default;
+
+ ::ndk::ScopedAStatus result(int32_t err, const vector<uint8_t>& msg,
+ const vector<uint8_t>& confToken) override {
+ error_ = err;
+ formattedMessage_ = msg;
+ confirmationToken_ = confToken;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ bool verifyConfirmationToken() {
+ static constexpr char confirmationPrefix[] = "confirmation token";
+ EXPECT_EQ(32U, confirmationToken_.size());
+ return 32U == confirmationToken_.size() &&
+ !memcmp(confirmationToken_.data(),
+ testHMAC(confirmationPrefix, formattedMessage_).data(), 32);
+ }
+
+ int error_;
+ vector<uint8_t> formattedMessage_;
+ vector<uint8_t> confirmationToken_;
+
+ private:
+ ConfirmationUIAidlTest& parent_;
+};
+
+struct CnCborDeleter {
+ void operator()(cn_cbor* ptr) { cn_cbor_free(ptr); }
+};
+
+typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
+
+// Simulates the User taping Ok
+TEST_P(ConfirmationUIAidlTest, UserOkTest) {
+ static constexpr char test_prompt[] = "Me first, gimme gimme!";
+ 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 + 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.
+ ASSERT_TRUE(confirmator_->deliverSecureInputEvent(makeTestToken(TestModeCommands::OK_EVENT))
+ .isOk());
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::OK, conf_cb->error_);
+
+ ASSERT_TRUE(conf_cb->verifyConfirmationToken());
+
+ cn_cbor_errback cn_cbor_error;
+ auto parsed_message = CnCborPtr(cn_cbor_decode(
+ conf_cb->formattedMessage_.data(), conf_cb->formattedMessage_.size(), &cn_cbor_error));
+ // is parsable CBOR
+ ASSERT_TRUE(parsed_message.get());
+ // is a map
+ ASSERT_EQ(CN_CBOR_MAP, parsed_message->type);
+
+ // the message must have exactly 2 key value pairs.
+ // cn_cbor holds 2*<no_of_pairs> in the length field
+ ASSERT_EQ(4, parsed_message->length);
+ // map has key "prompt"
+ auto prompt = cn_cbor_mapget_string(parsed_message.get(), "prompt");
+ ASSERT_TRUE(prompt);
+ ASSERT_EQ(CN_CBOR_TEXT, prompt->type);
+ ASSERT_EQ(22, prompt->length);
+ ASSERT_EQ(0, memcmp(test_prompt, prompt->v.str, 22));
+ // map has key "extra"
+ auto extra_out = cn_cbor_mapget_string(parsed_message.get(), "extra");
+ ASSERT_TRUE(extra_out);
+ ASSERT_EQ(CN_CBOR_BYTES, extra_out->type);
+ ASSERT_EQ(3, extra_out->length);
+ ASSERT_EQ(0, memcmp(test_extra, extra_out->v.bytes, 3));
+}
+
+// Initiates a confirmation prompt with a message that is too long
+TEST_P(ConfirmationUIAidlTest, MessageTooLongTest) {
+ static constexpr uint8_t test_extra[IConfirmationUI::MAX_MESSAGE_SIZE] = {};
+ 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 + 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));
+}
+
+// If the message gets very long some HAL implementations might fail even before the message
+// reaches the trusted app implementation. But the HAL must still diagnose the correct error.
+TEST_P(ConfirmationUIAidlTest, MessageWayTooLongTest) {
+ static constexpr uint8_t test_extra[(IConfirmationUI::MAX_MESSAGE_SIZE)*10] = {};
+ 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 + 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));
+}
+
+// Simulates the User tapping the Cancel
+TEST_P(ConfirmationUIAidlTest, UserCancelTest) {
+ static constexpr char test_prompt[] = "Me first, gimme gimme!";
+ 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 + 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.
+ ASSERT_TRUE(confirmator_->deliverSecureInputEvent(makeTestToken(TestModeCommands::CANCEL_EVENT))
+ .isOk());
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::CANCELED, conf_cb->error_);
+
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Simulates the framework cancelling an ongoing prompt
+TEST_P(ConfirmationUIAidlTest, AbortTest) {
+ static constexpr char test_prompt[] = "Me first, gimme gimme!";
+ 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 + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
+// the design guidelines.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest1) {
+ static constexpr char test_prompt[] =
+ "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
+ "WWWWWWWWWWWWWW";
+ 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 + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
+// the design guidelines in magnified mode.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest1Magnified) {
+ static constexpr char test_prompt[] =
+ "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
+ "WWWWWWWWWWWWWW";
+ 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 + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_
+ ->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+ {UIOption::ACCESSIBILITY_MAGNIFIED})
+ .isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
+// required by the design guidelines.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest2) {
+ static constexpr char test_prompt[] =
+ "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
+ "WWWWWWWWWWWW WWWWWWWWWWWW";
+ 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 + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
+// required by the design guidelines in magnified mode.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest2Magnified) {
+ static constexpr char test_prompt[] =
+ "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
+ "WWWWWWWWWWWW WWWWWWWWWWWW";
+ 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 + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_
+ ->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+ {UIOption::ACCESSIBILITY_MAGNIFIED})
+ .isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string that ends in the middle of a multibyte character
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test1) {
+ static constexpr char test_prompt[] = {char(0xc0), 0};
+ 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 + 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));
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string with a 5-byte character.
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test2) {
+ static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
+ char(0x82), char(0x82), 0};
+ 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 + 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));
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test3) {
+ static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
+ 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 + 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));
+}
+
+// Test the implementation of HMAC SHA 256 against a golden blob.
+TEST(ConfirmationUITestSelfTest, HMAC256SelfTest) {
+ const char key_str[32] = "keykeykeykeykeykeykeykeykeykeyk";
+ const uint8_t(&key)[32] = *reinterpret_cast<const uint8_t(*)[32]>(key_str);
+ auto expected = hex2str("2377fbcaa7fb3f6c20cfa1d9ebc60e9922cf58c909e25e300f3cb57f7805c886");
+ auto result = HMacer::hmac256(key, "value1", "value2", "value3");
+
+#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
+ hexdump(std::cout, reinterpret_cast<const uint8_t*>(expected.data()), 32) << std::endl;
+ hexdump(std::cout, result.value().data(), 32) << std::endl;
+#endif
+
+ ByteBufferProxy expected_bytes(expected);
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(expected, result.value());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConfirmationUIAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, ConfirmationUIAidlTest,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(IConfirmationUI::descriptor)),
+ ::android::PrintInstanceNameToString);
+
+} // namespace aidl::android::hardware::confirmationui::test
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
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/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl
new file mode 100644
index 0000000..b15d037
--- /dev/null
+++ b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.fastboot;
+@Backing(type="byte") @VintfStability
+enum FileSystemType {
+ EXT4 = 0,
+ F2FS = 1,
+ RAW = 2,
+}
diff --git a/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
new file mode 100644
index 0000000..445fcde
--- /dev/null
+++ b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.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/gatekeeper/1.0/vts/OWNERS b/gatekeeper/1.0/vts/OWNERS
index 738c710..ee2af97 100644
--- a/gatekeeper/1.0/vts/OWNERS
+++ b/gatekeeper/1.0/vts/OWNERS
@@ -1,3 +1,3 @@
-jdanis@google.com
+# Bug component: 1124862
swillden@google.com
guangzhu@google.com
diff --git a/gatekeeper/OWNERS b/gatekeeper/OWNERS
index d95b856..fddc2ff 100644
--- a/gatekeeper/OWNERS
+++ b/gatekeeper/OWNERS
@@ -1,2 +1,4 @@
+# Bug component: 1124862
swillden@google.com
guangzhu@google.com
+subrahmanyaman@google.com
diff --git a/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 390d8b5..95a14b2 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -9,6 +9,7 @@
aidl_interface {
name: "android.hardware.input.common",
+ host_supported: true,
vendor_available: true,
srcs: ["android/hardware/input/common/*.aidl"],
stability: "vintf",
diff --git a/input/processor/aidl/Android.bp b/input/processor/aidl/Android.bp
index 354816e..773bb49 100644
--- a/input/processor/aidl/Android.bp
+++ b/input/processor/aidl/Android.bp
@@ -9,6 +9,7 @@
aidl_interface {
name: "android.hardware.input.processor",
+ host_supported: true,
vendor_available: true,
srcs: ["android/hardware/input/processor/*.aidl"],
imports: [
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 613f31b..01d70cd 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -36,7 +36,7 @@
host_supported: true,
srcs: ["android/hardware/radio/config/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -48,7 +48,7 @@
versions_with_info: [
{
version: "1",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
},
],
@@ -60,7 +60,7 @@
host_supported: true,
srcs: ["android/hardware/radio/data/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -72,7 +72,7 @@
versions_with_info: [
{
version: "1",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
},
],
@@ -84,7 +84,7 @@
host_supported: true,
srcs: ["android/hardware/radio/messaging/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -96,7 +96,7 @@
versions_with_info: [
{
version: "1",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
},
],
@@ -108,7 +108,7 @@
host_supported: true,
srcs: ["android/hardware/radio/modem/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -120,7 +120,7 @@
versions_with_info: [
{
version: "1",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
},
],
@@ -132,7 +132,7 @@
host_supported: true,
srcs: ["android/hardware/radio/network/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -144,7 +144,7 @@
versions_with_info: [
{
version: "1",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
},
],
@@ -157,7 +157,7 @@
srcs: ["android/hardware/radio/sim/*.aidl"],
stability: "vintf",
imports: [
- "android.hardware.radio-V1",
+ "android.hardware.radio-V2",
"android.hardware.radio.config",
],
backend: {
@@ -172,7 +172,7 @@
{
version: "1",
imports: [
- "android.hardware.radio-V1",
+ "android.hardware.radio-V2",
"android.hardware.radio.config-V1",
],
},
@@ -186,7 +186,7 @@
host_supported: true,
srcs: ["android/hardware/radio/voice/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -198,7 +198,7 @@
versions_with_info: [
{
version: "1",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
},
],
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
index 0ffa1f7..5983afe 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -37,6 +37,10 @@
oneway void dataCallListChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.SetupDataCallResult[] dcList);
oneway void keepaliveStatus(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.KeepaliveStatus status);
oneway void pcoData(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.PcoDataInfo pco);
+ /**
+ * @deprecated use unthrottleDataProfile to clarify access network for this event.
+ */
oneway void unthrottleApn(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.DataProfileInfo dataProfileInfo);
oneway void slicingConfigChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.SlicingConfig slicingConfig);
+ oneway void unthrottleDataProfile(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.AccessNetwork accessNetwork, in android.hardware.radio.data.DataProfileInfo dataProfileInfo);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index 832738f..3b0c5e0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -40,6 +40,9 @@
oneway void getBarringInfo(in int serial);
oneway void getCdmaRoamingPreference(in int serial);
oneway void getCellInfoList(in int serial);
+ /**
+ * @deprecated use getRegistrationState()
+ */
oneway void getDataRegistrationState(in int serial);
oneway void getImsRegistrationState(in int serial);
oneway void getNetworkSelectionMode(in int serial);
@@ -47,6 +50,9 @@
oneway void getSignalStrength(in int serial);
oneway void getSystemSelectionChannels(in int serial);
oneway void getVoiceRadioTechnology(in int serial);
+ /**
+ * @deprecated use getRegistrationState()
+ */
oneway void getVoiceRegistrationState(in int serial);
oneway void isNrDualConnectivityEnabled(in int serial);
oneway void responseAcknowledgement();
@@ -74,4 +80,5 @@
oneway void triggerEmergencyNetworkScan(int serial, in android.hardware.radio.network.EmergencyNetworkScanTrigger request);
oneway void cancelEmergencyNetworkScan(in int serial);
oneway void exitEmergencyMode(in int serial);
+ oneway void getRegistrationState(in int serial, in android.hardware.radio.RadioTechnologyFamily ratFamily, in android.hardware.radio.network.Domain domain);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 24d587e..228451f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -41,6 +41,9 @@
oneway void getBarringInfoResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellIdentity cellIdentity, in android.hardware.radio.network.BarringInfo[] barringInfos);
oneway void getCdmaRoamingPreferenceResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CdmaRoamingType type);
oneway void getCellInfoListResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellInfo[] cellInfo);
+ /**
+ * @deprecated use getRegistrationStateResponse()
+ */
oneway void getDataRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RegStateResult dataRegResponse);
oneway void getImsRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isRegistered, in android.hardware.radio.RadioTechnologyFamily ratFamily);
oneway void getNetworkSelectionModeResponse(in android.hardware.radio.RadioResponseInfo info, in boolean manual);
@@ -48,6 +51,9 @@
oneway void getSignalStrengthResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.SignalStrength signalStrength);
oneway void getSystemSelectionChannelsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RadioAccessSpecifier[] specifiers);
oneway void getVoiceRadioTechnologyResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.RadioTechnology rat);
+ /**
+ * @deprecated use getRegistrationStateResponse()
+ */
oneway void getVoiceRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RegStateResult voiceRegResponse);
oneway void isNrDualConnectivityEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled);
oneway void setAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info);
@@ -73,4 +79,5 @@
oneway void triggerEmergencyNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void exitEmergencyModeResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void cancelEmergencyNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void getRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RegStateResult regResponse);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
index e5a0a70..0b2d733 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
@@ -41,6 +41,7 @@
const byte EMC_INDICATOR_NR_CONNECTED_TO_5GCN = 1;
const byte EMC_INDICATOR_EUTRA_CONNECTED_TO_5GCN = 2;
const byte EMC_INDICATOR_BOTH_NR_EUTRA_CONNECTED_TO_5GCN = 3;
+ const byte EMC_INDICATOR_EMC_OVER_NON_3GPP = 4;
const byte EMF_INDICATOR_NOT_SUPPORTED = 0;
const byte EMF_INDICATOR_NR_CONNECTED_TO_5GCN = 1;
const byte EMF_INDICATOR_EUTRA_CONNECTED_TO_5GCN = 2;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
index f0a03ae..c1e5c8d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
@@ -40,4 +40,5 @@
android.hardware.radio.network.CellIdentity cellIdentity;
String registeredPlmn;
android.hardware.radio.network.AccessTechnologySpecificInfo accessTechnologySpecificInfo;
+ android.hardware.radio.AccessNetwork accessNetwork = android.hardware.radio.AccessNetwork.UNKNOWN;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl
index 8ce689f..4a53a6d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl
@@ -39,6 +39,11 @@
UTRAN = 2,
EUTRAN = 3,
CDMA2000 = 4,
+ /**
+ * @deprecated should use N3ANEPS or N3AN5GS based on N3AN selection.
+ */
IWLAN = 5,
NGRAN = 6,
+ N3ANEPS = 5,
+ N3AN5GS = 7,
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl
index e6fdce2..5a8f403 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl
@@ -36,4 +36,5 @@
enum RadioTechnologyFamily {
THREE_GPP = 0,
THREE_GPP2 = 1,
+ NON_3GPP = 2,
}
diff --git a/radio/aidl/android/hardware/radio/AccessNetwork.aidl b/radio/aidl/android/hardware/radio/AccessNetwork.aidl
index 2885642..b85143d 100644
--- a/radio/aidl/android/hardware/radio/AccessNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/AccessNetwork.aidl
@@ -23,30 +23,39 @@
/**
* Unknown access network
*/
- UNKNOWN,
+ UNKNOWN = 0,
/**
* GSM EDGE Radio Access Network
*/
- GERAN,
+ GERAN = 1,
/**
* Universal Terrestrial Radio Access Network
*/
- UTRAN,
+ UTRAN = 2,
/**
* Evolved Universal Terrestrial Radio Access Network
*/
- EUTRAN,
+ EUTRAN = 3,
/**
* CDMA 2000 network
*/
- CDMA2000,
+ CDMA2000 = 4,
/**
- * Interworking Wireless LAN
+ * Interworking Wireless LAN.
+ * @deprecated should use N3ANEPS or N3AN5GS based on N3AN selection.
*/
- IWLAN,
+ IWLAN = 5,
/**
* Next-Generation Radio Access Network (NGRAN).
* Note NGRAN is only for standalone mode. Non-standalone mode uses AccessNetwork EUTRAN.
*/
- NGRAN,
+ NGRAN = 6,
+ /**
+ * Non-3GPP Access Network for EPS.
+ */
+ N3ANEPS = 5,
+ /**
+ * Non-3GPP Access Network for 5GS.
+ */
+ N3AN5GS = 7,
}
diff --git a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
index a2b989d..4f4bbcb 100644
--- a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
+++ b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
@@ -28,4 +28,8 @@
* 3GPP2 Technologies - CDMA
*/
THREE_GPP2,
+ /**
+ * Non 3GPP Technologies - IWLAN, N3IWF
+ */
+ NON_3GPP,
}
diff --git a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
index 938c695..b2e6ca4 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -16,6 +16,7 @@
package android.hardware.radio.data;
+import android.hardware.radio.AccessNetwork;
import android.hardware.radio.RadioIndicationType;
import android.hardware.radio.data.DataProfileInfo;
import android.hardware.radio.data.KeepaliveStatus;
@@ -71,6 +72,7 @@
*
* @param type Type of radio indication
* @param dataProfileInfo Data profile info.
+ * @deprecated use unthrottleDataProfile to clarify access network for this event.
*/
void unthrottleApn(in RadioIndicationType type, in DataProfileInfo dataProfileInfo);
@@ -86,4 +88,19 @@
*
*/
void slicingConfigChanged(in RadioIndicationType type, in SlicingConfig slicingConfig);
+
+ /**
+ * The modem can explicitly set SetupDataCallResult::suggestedRetryTime after a failure in
+ * IRadioData.SetupDataCall. During that time, no new calls are allowed to
+ * IRadioData.SetupDataCall that use the same APN(or DNN) in DataProfile.
+ * When IRadioDataIndication.unthrottleDataProfile is sent, AOSP will no longer throttle calls
+ * to IRadioData.SetupDataCall for the given APN(or DNN) in DataProfile.
+ *
+ * @param type Type of radio indication
+ * @param accessNetwork Access network this throttling occurred, this must match the access
+ * network passed in setup data call request.
+ * @param dataProfileInfo Data profile info.
+ */
+ void unthrottleDataProfile(in RadioIndicationType type, in AccessNetwork accessNetwork,
+ in DataProfileInfo dataProfileInfo);
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 0ac8b0e..c82fde2 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -17,7 +17,11 @@
package android.hardware.radio.network;
import android.hardware.radio.AccessNetwork;
+import android.hardware.radio.RadioTechnologyFamily;
import android.hardware.radio.network.CdmaRoamingType;
+import android.hardware.radio.network.Domain;
+import android.hardware.radio.network.EmergencyMode;
+import android.hardware.radio.network.EmergencyNetworkScanTrigger;
import android.hardware.radio.network.IRadioNetworkIndication;
import android.hardware.radio.network.IRadioNetworkResponse;
import android.hardware.radio.network.IndicationFilter;
@@ -27,8 +31,6 @@
import android.hardware.radio.network.RadioBandMode;
import android.hardware.radio.network.SignalThresholdInfo;
import android.hardware.radio.network.UsageSetting;
-import android.hardware.radio.network.EmergencyNetworkScanTrigger;
-import android.hardware.radio.network.EmergencyMode;
/**
* This interface is used by telephony and telecom to talk to cellular radio for network APIs.
@@ -103,6 +105,7 @@
* @param serial Serial number of request.
*
* Response function is IRadioNetworkResponse.getDataRegistrationStateResponse()
+ * @deprecated use getRegistrationState()
*/
void getDataRegistrationState(in int serial);
@@ -167,6 +170,7 @@
* @param serial Serial number of request.
*
* Response function is IRadioNetworkResponse.getVoiceRegistrationStateResponse()
+ * @deprecated use getRegistrationState()
*/
void getVoiceRegistrationState(in int serial);
@@ -449,7 +453,7 @@
*
* Response function is IRadioEmergencyResponse.setEmergencyModeResponse()
*/
- void setEmergencyMode(int serial, in EmergencyMode emcModeType );
+ void setEmergencyMode(int serial, in EmergencyMode emcModeType);
/**
* Triggers an Emergency network scan.
@@ -460,7 +464,7 @@
*
* Response function is IRadioEmergencyResponse.triggerEmergencyNetworkScanResponse()
*/
- void triggerEmergencyNetworkScan( int serial, in EmergencyNetworkScanTrigger request);
+ void triggerEmergencyNetworkScan(int serial, in EmergencyNetworkScanTrigger request);
/**
* Cancels ongoing Emergency network scan
@@ -479,4 +483,15 @@
* Response function is IRadioEmergencyResponse.exitEmergencyModeResponse()
*/
void exitEmergencyMode(in int serial);
+
+ /**
+ * Request current registration state.
+ *
+ * @param serial Serial number of request.
+ * @param ratFamily RadioTechnologyFamily of request.
+ * @param domain Domain PS or CS of request.
+ *
+ * Response function is IRadioNetworkResponse.getRegistrationStateResponse()
+ */
+ void getRegistrationState(in int serial, in RadioTechnologyFamily ratFamily, in Domain domain);
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 243e949..69d53ee 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -23,13 +23,13 @@
import android.hardware.radio.network.CdmaRoamingType;
import android.hardware.radio.network.CellIdentity;
import android.hardware.radio.network.CellInfo;
+import android.hardware.radio.network.EmergencyRegResult;
import android.hardware.radio.network.OperatorInfo;
import android.hardware.radio.network.RadioAccessSpecifier;
import android.hardware.radio.network.RadioBandMode;
import android.hardware.radio.network.RegStateResult;
import android.hardware.radio.network.SignalStrength;
import android.hardware.radio.network.UsageSetting;
-import android.hardware.radio.network.EmergencyRegResult;
/**
* Interface declaring response functions to solicited radio requests for network APIs.
@@ -153,6 +153,8 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
* RadioError:NOT_PROVISIONED
+ *
+ * @deprecated use getRegistrationStateResponse()
*/
void getDataRegistrationStateResponse(
in RadioResponseInfo info, in RegStateResult dataRegResponse);
@@ -259,6 +261,8 @@
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
+ *
+ * @deprecated use getRegistrationStateResponse()
*/
void getVoiceRegistrationStateResponse(
in RadioResponseInfo info, in RegStateResult voiceRegResponse);
@@ -616,4 +620,16 @@
* RadioError:MODEM_ERR
*/
void cancelEmergencyNetworkScanResponse(in RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param regResponse Current registration response as defined by RegStateResult
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NOT_PROVISIONED
+ */
+ void getRegistrationStateResponse(in RadioResponseInfo info, in RegStateResult regResponse);
}
diff --git a/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl b/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
index 197f401..2b0b7c9 100644
--- a/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
@@ -39,6 +39,10 @@
* Emergency services supported in NR connected to 5GCN and E-UTRA connected to 5GCN
*/
const byte EMC_INDICATOR_BOTH_NR_EUTRA_CONNECTED_TO_5GCN = 3;
+ /**
+ * Emergency services supported over 5G N3GPP access.
+ */
+ const byte EMC_INDICATOR_EMC_OVER_NON_3GPP = 4;
/**
* Emergency services fallback not supported
@@ -96,6 +100,7 @@
* NR REGISTRATION ACCEPT.
* Refer 3GPP 24.501 EPS 5GS network feature support -> EMF
* Values are EMF_INDICATOR_ from TS 24.501 sec 9.10.3.5.
+ * Not Applicable for the registration via non-3GPP access.
*/
byte emfSupported;
}
diff --git a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
index 3d96b8c..979b4b8 100644
--- a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
@@ -16,6 +16,7 @@
package android.hardware.radio.network;
+import android.hardware.radio.AccessNetwork;
import android.hardware.radio.RadioTechnology;
import android.hardware.radio.network.AccessTechnologySpecificInfo;
import android.hardware.radio.network.CellIdentity;
@@ -59,4 +60,8 @@
* Access-technology-specific registration information, such as for CDMA2000.
*/
AccessTechnologySpecificInfo accessTechnologySpecificInfo;
+ /**
+ * Indicates the access network used for this registration.
+ */
+ AccessNetwork accessNetwork = AccessNetwork.UNKNOWN;
}
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index f79e045..2f7fc59 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -31,12 +31,13 @@
"-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
],
shared_libs: [
+ "android.hardware.radio-V2-ndk",
"android.hardware.radio.config-V1-ndk",
"android.hardware.radio.config@1.0",
"android.hardware.radio.config@1.1",
"android.hardware.radio.config@1.2",
"android.hardware.radio.config@1.3",
- "android.hardware.radio.data-V1-ndk",
+ "android.hardware.radio.data-V2-ndk",
"android.hardware.radio.messaging-V1-ndk",
"android.hardware.radio.modem-V1-ndk",
"android.hardware.radio.network-V2-ndk",
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
index c714190..c886267 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -99,6 +99,9 @@
scanTrigger) override;
::ndk::ScopedAStatus cancelEmergencyNetworkScan(int32_t serial) override;
::ndk::ScopedAStatus exitEmergencyMode(int32_t serial) override;
+ ::ndk::ScopedAStatus getRegistrationState(
+ int32_t serial, ::aidl::android::hardware::radio::RadioTechnologyFamily ratFamily,
+ ::aidl::android::hardware::radio::network::Domain domain) override;
protected:
std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond();
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index ff30ac3..638b34e 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -340,4 +340,16 @@
return ok();
}
+ScopedAStatus RadioNetwork::getRegistrationState(
+ int32_t serial, ::aidl::android::hardware::radio::RadioTechnologyFamily ratFamily,
+ aidl::Domain domain) {
+ LOG_CALL << serial;
+ if (ratFamily == ::aidl::android::hardware::radio::RadioTechnologyFamily::THREE_GPP &&
+ domain == aidl::Domain::PS) {
+ LOG_CALL << " Radio Technology Family 3GPP and Domain PS";
+ }
+ LOG(ERROR) << " geRegistrationState is unsupported by HIDL HALs";
+ respond()->getRegistrationStateResponse(notSupported(serial), {});
+ return ok();
+}
} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
index 4dbaef4..45a3497 100644
--- a/radio/aidl/compat/service/Android.bp
+++ b/radio/aidl/compat/service/Android.bp
@@ -34,12 +34,13 @@
],
shared_libs: [
"android.hardware.radio-library.compat",
+ "android.hardware.radio-V2-ndk",
"android.hardware.radio.config-V1-ndk",
"android.hardware.radio.config@1.0",
"android.hardware.radio.config@1.1",
"android.hardware.radio.config@1.2",
"android.hardware.radio.config@1.3",
- "android.hardware.radio.data-V1-ndk",
+ "android.hardware.radio.data-V2-ndk",
"android.hardware.radio.messaging-V1-ndk",
"android.hardware.radio.modem-V1-ndk",
"android.hardware.radio.network-V2-ndk",
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index 0d4bb3e..ba68728 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -63,9 +63,9 @@
"libvintf",
],
static_libs: [
- "android.hardware.radio-V1-ndk",
+ "android.hardware.radio-V2-ndk",
"android.hardware.radio.config-V1-ndk",
- "android.hardware.radio.data-V1-ndk",
+ "android.hardware.radio.data-V2-ndk",
"android.hardware.radio.messaging-V1-ndk",
"android.hardware.radio.modem-V1-ndk",
"android.hardware.radio.network-V2-ndk",
diff --git a/radio/aidl/vts/radio_data_indication.cpp b/radio/aidl/vts/radio_data_indication.cpp
index 61e079e..213505d 100644
--- a/radio/aidl/vts/radio_data_indication.cpp
+++ b/radio/aidl/vts/radio_data_indication.cpp
@@ -42,3 +42,10 @@
RadioIndicationType /*type*/, const SlicingConfig& /*slicingConfig*/) {
return ndk::ScopedAStatus::ok();
}
+
+ndk::ScopedAStatus RadioDataIndication::unthrottleDataProfile(
+ RadioIndicationType /*type*/,
+ ::aidl::android::hardware::radio::AccessNetwork /*accessNetwork*/,
+ const DataProfileInfo& /*dataProfileInfo*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_data_utils.h b/radio/aidl/vts/radio_data_utils.h
index fb91ef6..cfb2ab2 100644
--- a/radio/aidl/vts/radio_data_utils.h
+++ b/radio/aidl/vts/radio_data_utils.h
@@ -97,6 +97,9 @@
const DataProfileInfo& dataProfile) override;
virtual ndk::ScopedAStatus slicingConfigChanged(RadioIndicationType type,
const SlicingConfig& slicingConfig) override;
+ virtual ndk::ScopedAStatus unthrottleDataProfile(
+ RadioIndicationType type, ::aidl::android::hardware::radio::AccessNetwork accessNetwork,
+ const DataProfileInfo& dataProfile) override;
};
// The main test class for Radio AIDL Data.
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
index 5599c03..ff58ecd 100644
--- a/radio/aidl/vts/radio_network_response.cpp
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -293,3 +293,11 @@
parent_network.notify(info.serial);
return ndk::ScopedAStatus::ok();
}
+
+ndk::ScopedAStatus RadioNetworkResponse::getRegistrationStateResponse(
+ const RadioResponseInfo& info, const RegStateResult& regResponse) {
+ rspInfo = info;
+ regResp = regResponse;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index 25c42d3..054b69e 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -15,7 +15,9 @@
*/
#include <aidl/android/hardware/radio/RadioAccessFamily.h>
+#include <aidl/android/hardware/radio/RadioTechnologyFamily.h>
#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/network/Domain.h>
#include <aidl/android/hardware/radio/network/IndicationFilter.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
@@ -1911,3 +1913,91 @@
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
LOG(DEBUG) << "exitEmergencyMode finished";
}
+
+/*
+ * Test IRadioNetwork.getRegistrationState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getRegistrationState) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->getRegistrationState(
+ serial, RadioTechnologyFamily::THREE_GPP, Domain::PS);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("getRegistrationStateResponse, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::NOT_PROVISIONED}));
+ // Check the mcc [0, 999] and mnc [0, 999].
+ std::string mcc;
+ std::string mnc;
+ bool checkMccMnc = true;
+ CellIdentity cellIdentity = radioRsp_network->regResp.cellIdentity;
+ switch (cellIdentity.getTag()) {
+ case CellIdentity::noinit: {
+ checkMccMnc = false;
+ break;
+ }
+ case CellIdentity::gsm: {
+ CellIdentityGsm cig = cellIdentity.get<CellIdentity::gsm>();
+ mcc = cig.mcc;
+ mnc = cig.mnc;
+ break;
+ }
+ case CellIdentity::wcdma: {
+ CellIdentityWcdma ciw = cellIdentity.get<CellIdentity::wcdma>();
+ mcc = ciw.mcc;
+ mnc = ciw.mnc;
+ break;
+ }
+ case CellIdentity::tdscdma: {
+ CellIdentityTdscdma cit = cellIdentity.get<CellIdentity::tdscdma>();
+ mcc = cit.mcc;
+ mnc = cit.mnc;
+ break;
+ }
+ case CellIdentity::cdma: {
+ // CellIdentityCdma has no mcc/mnc
+ CellIdentityCdma cic = cellIdentity.get<CellIdentity::cdma>();
+ checkMccMnc = false;
+ break;
+ }
+ case CellIdentity::lte: {
+ CellIdentityLte cil = cellIdentity.get<CellIdentity::lte>();
+ mcc = cil.mcc;
+ mnc = cil.mnc;
+ break;
+ }
+ case CellIdentity::nr: {
+ CellIdentityNr cin = cellIdentity.get<CellIdentity::nr>();
+ mcc = cin.mcc;
+ mnc = cin.mnc;
+ break;
+ }
+ }
+
+ // 32 bit system might return invalid mcc and mnc string "\xff\xff..."
+ if (checkMccMnc && mcc.size() < 4 && mnc.size() < 4) {
+ int mcc_int = stoi(mcc);
+ int mnc_int = stoi(mnc);
+ EXPECT_TRUE(mcc_int >= 0 && mcc_int <= 999);
+ EXPECT_TRUE(mnc_int >= 0 && mnc_int <= 999);
+ }
+
+ // Check for access technology specific info
+ AccessTechnologySpecificInfo info = radioRsp_network->regResp.accessTechnologySpecificInfo;
+ RadioTechnology rat = radioRsp_network->regResp.rat;
+ // TODO: add logic for cdmaInfo
+ if (rat == RadioTechnology::LTE || rat == RadioTechnology::LTE_CA) {
+ ASSERT_EQ(info.getTag(), AccessTechnologySpecificInfo::eutranInfo);
+ } else if (rat == RadioTechnology::NR) {
+ ASSERT_EQ(info.getTag(), AccessTechnologySpecificInfo::ngranNrVopsInfo);
+ }
+ AccessNetwork an = radioRsp_network->regResp.accessNetwork;
+ ASSERT_NE(an, AccessNetwork::N3AN5GS);
+ ASSERT_NE(an, AccessNetwork::N3ANEPS);
+}
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
index 8480825..f30b742 100644
--- a/radio/aidl/vts/radio_network_utils.h
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -42,6 +42,7 @@
int networkTypeBitmapResponse;
RegStateResult voiceRegResp;
RegStateResult dataRegResp;
+ RegStateResult regResp;
CellIdentity barringCellIdentity;
std::vector<BarringInfo> barringInfoList;
UsageSetting usageSetting;
@@ -158,6 +159,9 @@
virtual ndk::ScopedAStatus cancelEmergencyNetworkScanResponse(
const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getRegistrationStateResponse(
+ const RadioResponseInfo& info, const RegStateResult& regResponse) override;
};
/* Callback class for radio network indication */
diff --git a/security/keymint/RKP_CHANGELOG.md b/security/keymint/RKP_CHANGELOG.md
index dfcc938..243fc26 100644
--- a/security/keymint/RKP_CHANGELOG.md
+++ b/security/keymint/RKP_CHANGELOG.md
@@ -21,13 +21,13 @@
## IRemotelyProvisionedComponent 2 -> 3
* ProtectedData has been removed.
* DeviceInfo
- * `cert_type` has been added, with values corresponding to `widevine` or `keymint`
* `version` has moved to a top-level field within the CSR generated by the HAL
* IRemotelyProvisionedComponent
* The need for an EEK has been removed. There is no longer an encrypted portion of the CSR.
* Test mode has been removed.
* The schema for the CSR itself has been significantly simplified, please see
- IRemotelyProvisionedComponent.aidl for more details.
- * Notably, the chain of signing, MACing, and encryption operations has been replaced with a single
+ IRemotelyProvisionedComponent.aidl for more details. Notably,
+ * the chain of signing, MACing, and encryption operations has been replaced with a single
COSE_Sign1 object.
+ * CertificateType has been added to identify the type of certificate being requested.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index 6954d65..f0af619 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -49,7 +49,6 @@
* "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"
* }
*/
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..86c1717 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)
*
@@ -314,38 +315,50 @@
*
* @return the following CBOR Certificate Signing Request (Csr) serialized into a byte array:
*
- * Csr = [
- * version: 3, ; The CDDL Schema version.
- * UdsCerts,
- * DiceCertChain,
- * SignedData
- * ]
+ * Csr = AuthenticatedMessage<CsrPayload>
*
- * ; COSE_Sign1 (untagged)
- * SignedData = [
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * unprotected: {},
- * payload: bstr .cbor SignedDataPayload,
- * signature: bstr ; PureEd25519(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct) /
- * ; ECDSA(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct)
- * ]
- *
- * ; Sig_structure for SignedData
- * SignedDataSigStruct = [
- * context: "Signature1",
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor SignedDataPayload
- * ]
- *
- * SignedDataPayload = [ ; CBOR Array defining the payload for SignedData
+ * CsrPayload = [ ; CBOR Array defining the payload for Csr
+ * version: 1, ; The CsrPayload CDDL Schema version.
+ * CertificateType, ; The type of certificate being requested.
* DeviceInfo, ; Defined in DeviceInfo.aidl
* challenge: bstr .size (32..64), ; Provided by the method parameters
* KeysToSign, ; Provided by the method parameters
* ]
*
+ * ; 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
+ *
* KeysToSign = [ * PublicKey ] ; Please see MacedPublicKey.aidl for the PublicKey definition.
*
+ * AuthenticatedMessage<T> = [
+ * version: 3, ; The AuthenticatedMessage CDDL Schema version.
+ * UdsCerts,
+ * DiceCertChain,
+ * SignedData<T>,
+ * ]
+ *
+ * ; COSE_Sign1 (untagged)
+ * SignedData<T> = [
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * unprotected: {},
+ * payload: bstr .cbor T / nil,
+ * signature: bstr ; PureEd25519(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct<T>) /
+ * ; ECDSA(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct<T>)
+ * ]
+ *
+ * ; Sig_structure for SignedData
+ * SignedDataSigStruct<T> = [
+ * context: "Signature1",
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * external_aad: bstr .size 0,
+ * payload: bstr .cbor T
+ * ]
+ *
* ; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
* ; example, this could be provided by the hardware vendor, who certifies all of their chips.
* ; The SignerName is a free-form string describing who generated the signature. The root
@@ -365,7 +378,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 +391,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 +421,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/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
new file mode 100644
index 0000000..50be508
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
@@ -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
+ *
+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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.thermal;
+@VintfStability
+parcelable CoolingDevice {
+ android.hardware.thermal.CoolingType type;
+ String name;
+ long value;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
new file mode 100644
index 0000000..57c8939
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.thermal;
+@Backing(type="int") @VintfStability
+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/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
new file mode 100644
index 0000000..0aed5ec
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.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/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
new file mode 100644
index 0000000..6b3f922
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.thermal;
+@VintfStability
+interface IThermalChangedCallback {
+ oneway void notifyThrottling(in android.hardware.thermal.Temperature temperature);
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl
new file mode 100644
index 0000000..7156415
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.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
+ *
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.thermal;
+@VintfStability
+parcelable Temperature {
+ android.hardware.thermal.TemperatureType type;
+ String name;
+ float value;
+ android.hardware.thermal.ThrottlingSeverity throttlingStatus;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl
new file mode 100644
index 0000000..6da561f
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.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
+ *
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.thermal;
+@VintfStability
+parcelable TemperatureThreshold {
+ android.hardware.thermal.TemperatureType type;
+ String name;
+ float[] hotThrottlingThresholds;
+ float[] coldThrottlingThresholds;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
new file mode 100644
index 0000000..c6a08c1
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.thermal;
+@Backing(type="int") @VintfStability
+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/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
new file mode 100644
index 0000000..e86b581
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.thermal;
+@Backing(type="int") @VintfStability
+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/thermal/aidl/android/hardware/thermal/CoolingType.aidl b/thermal/aidl/android/hardware/thermal/CoolingType.aidl
new file mode 100644
index 0000000..1b430d2
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/CoolingType.aidl
@@ -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.
+ */
+
+package android.hardware.thermal;
+
+/**
+ * Device cooling device types
+ */
+@VintfStability
+@Backing(type="int")
+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
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl
index 450cd79..4648712 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl
@@ -43,4 +43,5 @@
void stop();
void flush();
void close();
+ void setStatusCheckIntervalHint(in long milliseconds);
}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl
index 0534f9d..4cb5b15 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl
@@ -18,7 +18,6 @@
import android.hardware.common.fmq.MQDescriptor;
import android.hardware.common.fmq.SynchronizedReadWrite;
-
import android.hardware.tv.tuner.DvrSettings;
import android.hardware.tv.tuner.IFilter;
@@ -101,4 +100,12 @@
* instance any more and all methods should return a failure.
*/
void close();
+
+ /**
+ * Set status check time interval.
+ *
+ * This time interval hint will be used by the Dvr to decide how often
+ * to evaluate data.
+ */
+ void setStatusCheckIntervalHint(in long milliseconds);
}
diff --git a/tv/tuner/aidl/default/Android.bp b/tv/tuner/aidl/default/Android.bp
index c10ad22..65fa821 100644
--- a/tv/tuner/aidl/default/Android.bp
+++ b/tv/tuner/aidl/default/Android.bp
@@ -29,7 +29,7 @@
],
shared_libs: [
"android.hardware.common.fmq-V1-ndk",
- "android.hardware.tv.tuner-V1-ndk",
+ "android.hardware.tv.tuner-V2-ndk",
"libbase",
"libbinder_ndk",
"libcutils",
diff --git a/tv/tuner/aidl/default/Dvr.cpp b/tv/tuner/aidl/default/Dvr.cpp
index 9928a59..c9dd8ee 100644
--- a/tv/tuner/aidl/default/Dvr.cpp
+++ b/tv/tuner/aidl/default/Dvr.cpp
@@ -154,6 +154,14 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus Dvr::setStatusCheckIntervalHint(int64_t /* in_milliseconds */) {
+ ALOGV("%s", __FUNCTION__);
+
+ // There is no active polling in this default implementation,
+ // so directly return ok here.
+ return ::ndk::ScopedAStatus::ok();
+}
+
bool Dvr::createDvrMQ() {
ALOGV("%s", __FUNCTION__);
diff --git a/tv/tuner/aidl/default/Dvr.h b/tv/tuner/aidl/default/Dvr.h
index 6ff71cd..293c533 100644
--- a/tv/tuner/aidl/default/Dvr.h
+++ b/tv/tuner/aidl/default/Dvr.h
@@ -70,6 +70,7 @@
::ndk::ScopedAStatus stop() override;
::ndk::ScopedAStatus flush() override;
::ndk::ScopedAStatus close() override;
+ ::ndk::ScopedAStatus setStatusCheckIntervalHint(int64_t in_milliseconds) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
diff --git a/tv/tuner/aidl/vts/functional/Android.bp b/tv/tuner/aidl/vts/functional/Android.bp
index e5fb1e6..6a71544 100644
--- a/tv/tuner/aidl/vts/functional/Android.bp
+++ b/tv/tuner/aidl/vts/functional/Android.bp
@@ -53,7 +53,7 @@
"android.hardware.cas@1.2",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
- "android.hardware.tv.tuner-V1-ndk",
+ "android.hardware.tv.tuner-V2-ndk",
"libaidlcommonsupport",
"libfmq",
"libcutils",
diff --git a/tv/tuner/aidl/vts/functional/DvrTests.cpp b/tv/tuner/aidl/vts/functional/DvrTests.cpp
index a9c3b51..50f4de2 100644
--- a/tv/tuner/aidl/vts/functional/DvrTests.cpp
+++ b/tv/tuner/aidl/vts/functional/DvrTests.cpp
@@ -323,3 +323,41 @@
ASSERT_TRUE(mDvrRecord);
ASSERT_TRUE(mDvrRecord->close().isOk());
}
+
+AssertionResult DvrTests::setPlaybackStatusCheckIntervalHint(int64_t milliseconds) {
+ ndk::ScopedAStatus status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+ status = mDvrPlayback->setStatusCheckIntervalHint(milliseconds);
+
+ if (getDvrPlaybackInterfaceVersion() < 2) {
+ return AssertionResult(status.getStatus() == STATUS_UNKNOWN_TRANSACTION);
+ }
+ return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::setRecordStatusCheckIntervalHint(int64_t milliseconds) {
+ ndk::ScopedAStatus status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+ status = mDvrRecord->setStatusCheckIntervalHint(milliseconds);
+
+ if (getDvrRecordInterfaceVersion() < 2) {
+ return AssertionResult(status.getStatus() == STATUS_UNKNOWN_TRANSACTION);
+ }
+ return AssertionResult(status.isOk());
+}
+
+int32_t DvrTests::getDvrPlaybackInterfaceVersion() {
+ int32_t version;
+ mDvrPlayback->getInterfaceVersion(&version);
+ return version;
+}
+
+int32_t DvrTests::getDvrRecordInterfaceVersion() {
+ int32_t version;
+ mDvrRecord->getInterfaceVersion(&version);
+ return version;
+}
diff --git a/tv/tuner/aidl/vts/functional/DvrTests.h b/tv/tuner/aidl/vts/functional/DvrTests.h
index 6662637..a88ba24 100644
--- a/tv/tuner/aidl/vts/functional/DvrTests.h
+++ b/tv/tuner/aidl/vts/functional/DvrTests.h
@@ -162,8 +162,12 @@
AssertionResult startDvrPlayback();
AssertionResult stopDvrRecord();
AssertionResult startDvrRecord();
+ AssertionResult setPlaybackStatusCheckIntervalHint(int64_t milliseconds);
+ AssertionResult setRecordStatusCheckIntervalHint(int64_t milliseconds);
void closeDvrPlayback();
void closeDvrRecord();
+ int32_t getDvrPlaybackInterfaceVersion();
+ int32_t getDvrRecordInterfaceVersion();
protected:
static AssertionResult failure() { return ::testing::AssertionFailure(); }
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 9a17d05..6aa1e16 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -241,6 +241,28 @@
ASSERT_TRUE(mDemuxTests.closeDemux());
}
+void TunerPlaybackAidlTest::setStatusCheckIntervalHintTest(int64_t statusCheckIntervalHint,
+ DvrConfig dvrConf) {
+ int32_t demuxId;
+ std::shared_ptr<IDemux> demux;
+
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ mDvrTests.setDemux(demux);
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+
+ ASSERT_TRUE(mDvrTests.setPlaybackStatusCheckIntervalHint(statusCheckIntervalHint));
+
+ mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile,
+ dvrConf.settings.get<DvrSettings::Tag::playback>());
+ ASSERT_TRUE(mDvrTests.startDvrPlayback());
+ mDvrTests.stopPlaybackThread();
+ ASSERT_TRUE(mDvrTests.stopDvrPlayback());
+ mDvrTests.closeDvrPlayback();
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
void TunerRecordAidlTest::recordSingleFilterTestWithLnb(FilterConfig filterConf,
FrontendConfig frontendConf,
DvrConfig dvrConf, LnbConfig lnbConf) {
@@ -426,6 +448,45 @@
ASSERT_TRUE(mDemuxTests.closeDemux());
}
+void TunerRecordAidlTest::setStatusCheckIntervalHintTest(int64_t statusCheckIntervalHint,
+ FrontendConfig frontendConf,
+ DvrConfig dvrConf) {
+ int32_t demuxId;
+ std::shared_ptr<IDemux> demux;
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ mDvrTests.setDemux(demux);
+
+ DvrConfig dvrSourceConfig;
+ if (record.hasFrontendConnection) {
+ int32_t feId;
+ mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ } else {
+ dvrSourceConfig = dvrMap[record.dvrSourceId];
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrSourceConfig.settings));
+ ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+ }
+
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
+
+ ASSERT_TRUE(mDvrTests.setRecordStatusCheckIntervalHint(statusCheckIntervalHint));
+
+ ASSERT_TRUE(mDvrTests.startDvrRecord());
+ ASSERT_TRUE(mDvrTests.stopDvrRecord());
+ mDvrTests.closeDvrRecord();
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+
+ if (record.hasFrontendConnection) {
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
+ }
+}
+
void TunerDescramblerAidlTest::scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
FrontendConfig frontendConf,
DescramblerConfig descConfig,
@@ -1000,6 +1061,18 @@
}
}
+TEST_P(TunerPlaybackAidlTest, SetStatusCheckIntervalHintToPlaybackTest) {
+ description("Set status check interval hint to playback test.");
+ if (!playback.support) {
+ return;
+ }
+ vector<DvrPlaybackHardwareConnections> playback_configs = generatePlaybackConfigs();
+ for (auto& configuration : playback_configs) {
+ playback = configuration;
+ setStatusCheckIntervalHintTest(STATUS_CHECK_INTERVAL_MS, dvrMap[playback.dvrId]);
+ }
+}
+
TEST_P(TunerRecordAidlTest, RecordDataFlowWithTsRecordFilterTest) {
description("Feed ts data from frontend to recording and test with ts record filter");
if (!record.support) {
@@ -1046,6 +1119,19 @@
}
}
+TEST_P(TunerRecordAidlTest, SetStatusCheckIntervalHintToRecordTest) {
+ description("Set status check interval hint to record test.");
+ if (!record.support) {
+ return;
+ }
+ auto record_configs = generateRecordConfigurations();
+ for (auto& configuration : record_configs) {
+ record = configuration;
+ setStatusCheckIntervalHintTest(STATUS_CHECK_INTERVAL_MS, frontendMap[record.frontendId],
+ dvrMap[record.dvrRecordId]);
+ }
+}
+
TEST_P(TunerFrontendAidlTest, TuneFrontend) {
description("Tune one Frontend with specific setting and check Lock event");
if (!live.hasFrontendConnection) {
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
index f68e1ec..3bfa78f 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
@@ -255,6 +255,8 @@
AssertionResult filterDataOutputTest();
void playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf);
+
+ void setStatusCheckIntervalHintTest(int64_t milliseconds, DvrConfig dvrConf);
};
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerPlaybackAidlTest);
@@ -294,6 +296,8 @@
DvrConfig dvrConf, LnbConfig lnbConf);
void recordSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf,
DvrConfig dvrConf, Dataflow_Context context);
+ void setStatusCheckIntervalHintTest(int64_t milliseconds, FrontendConfig frontendConf,
+ DvrConfig dvrConf);
std::shared_ptr<ITuner> mService;
FrontendTests mFrontendTests;
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
index fea5f83..516cb62 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
@@ -55,6 +55,7 @@
const string configFilePath = "/vendor/etc/tuner_vts_config_aidl_V1.xml";
#define FILTER_MAIN_TYPE_BIT_COUNT 5
+#define STATUS_CHECK_INTERVAL_MS 100L
// Hardware configs
static map<string, FrontendConfig> frontendMap;
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
index 00cae32..671cd85 100644
--- a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
+++ b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
@@ -37,10 +37,8 @@
"libutils",
],
sanitize: {
- address: true,
undefined: true,
all_undefined: true,
- fuzzer: true,
cfi: true,
integer_overflow: true,
scs: true,