Merge "Add new aidl interface for android.hardware.bluetooth.audio"
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
index 82f98d8..1031ebb 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
@@ -23,6 +23,7 @@
* This requests Android to enter its normal operating state.
* This may be sent after the AP has reported
* VehicleApPowerStateReport#DEEP_SLEEP_EXIT,
+ * VehicleApPowerStateReport#HIBERNATION_EXIT,
* VehicleApPowerStateReport#SHUTDOWN_CANCELLED, or
* VehicleApPowerStateReport#WAIT_FOR_VHAL.
*/
@@ -31,6 +32,7 @@
* The power controller issues this request to shutdown the system.
* This may be sent after the AP has reported
* VehicleApPowerStateReport#DEEP_SLEEP_EXIT,
+ * VehicleApPowerStateReport#HIBERNATION_EXIT,
* VehicleApPowerStateReport#ON,
* VehicleApPowerStateReport#SHUTDOWN_CANCELLED,
* VehicleApPowerStateReport#SHUTDOWN_POSTPONE,
@@ -59,6 +61,7 @@
* Completes the shutdown process.
* This may be sent after the AP has reported
* VehicleApPowerStateReport#DEEP_SLEEP_ENTRY or
+ * VehicleApPowerStateReport#HIBERNATION_ENTRY or
* VehicleApPowerStateReport#SHUTDOWN_START. The AP will not report new
* state information after receiving this request.
*/
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index dd5d7c5..a781b35 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -229,9 +229,8 @@
<regex-instance>.*</regex-instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="aidl" optional="true">
<name>android.hardware.dumpstate</name>
- <version>1.1</version>
<interface>
<name>IDumpstateDevice</name>
<instance>default</instance>
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
new file mode 100644
index 0000000..e18eade
--- /dev/null
+++ b/dumpstate/aidl/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2021 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.dumpstate",
+ vendor_available: true,
+ srcs: ["android/hardware/dumpstate/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ ndk: {
+ separate_platform_variant: false,
+ vndk: {
+ enabled: true,
+ },
+ },
+ },
+}
diff --git a/dumpstate/aidl/aidl_api/android.hardware.dumpstate/current/android/hardware/dumpstate/IDumpstateDevice.aidl b/dumpstate/aidl/aidl_api/android.hardware.dumpstate/current/android/hardware/dumpstate/IDumpstateDevice.aidl
new file mode 100644
index 0000000..4d78a4c
--- /dev/null
+++ b/dumpstate/aidl/aidl_api/android.hardware.dumpstate/current/android/hardware/dumpstate/IDumpstateDevice.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.dumpstate;
+@VintfStability
+interface IDumpstateDevice {
+ void dumpstateBoard(in ParcelFileDescriptor[] fd, in android.hardware.dumpstate.IDumpstateDevice.DumpstateMode mode, in long timeoutMillis);
+ boolean getVerboseLoggingEnabled();
+ void setVerboseLoggingEnabled(in boolean enable);
+ const int ERROR_UNSUPPORTED_MODE = 1;
+ const int ERROR_DEVICE_LOGGING_NOT_ENABLED = 2;
+ @Backing(type="int") @VintfStability
+ enum DumpstateMode {
+ FULL = 0,
+ INTERACTIVE = 1,
+ REMOTE = 2,
+ WEAR = 3,
+ CONNECTIVITY = 4,
+ WIFI = 5,
+ DEFAULT = 6,
+ PROTO = 7,
+ }
+}
diff --git a/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl b/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl
new file mode 100644
index 0000000..3b42546
--- /dev/null
+++ b/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2021 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.dumpstate;
+
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+interface IDumpstateDevice {
+ /**
+ * Constants that define the type of bug report being taken to restrict content appropriately.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum DumpstateMode {
+ /**
+ * Takes a bug report without user interference.
+ */
+ FULL = 0,
+ /**
+ * Interactive bug report, i.e. triggered by the user.
+ */
+ INTERACTIVE = 1,
+ /**
+ * Remote bug report triggered by DevicePolicyManager, for example.
+ */
+ REMOTE = 2,
+ /**
+ * Bug report triggered on a wear device.
+ */
+ WEAR = 3,
+ /**
+ * Bug report limited to only connectivity info (cellular, wifi, and networking). Sometimes
+ * called "telephony" in legacy contexts.
+ *
+ * All reported information MUST directly relate to connectivity debugging or customer
+ * support and MUST NOT contain unrelated private information. This information MUST NOT
+ * identify user-installed packages (UIDs are OK, package names are not), and MUST NOT
+ * contain logs of user application traffic.
+ */
+ CONNECTIVITY = 4,
+ /**
+ * Bug report limited to only wifi info.
+ */
+ WIFI = 5,
+ /**
+ * Default mode, This mode MUST be supported if the
+ * dumpstate HAL is implemented.
+ */
+ DEFAULT = 6,
+ /**
+ * Takes a report in protobuf.
+ *
+ * The content, if implemented, must be a binary protobuf message written to the first file
+ * descriptor of the native handle. The protobuf schema shall be defined by the vendor.
+ */
+ PROTO = 7,
+ }
+
+ /**
+ * Returned for cases where the device doesn't support the given DumpstateMode (e.g. a phone
+ * trying to use DumpstateMode::WEAR).
+ */
+ const int ERROR_UNSUPPORTED_MODE = 1;
+ /**
+ * Returned when device logging is not enabled.
+ */
+ const int ERROR_DEVICE_LOGGING_NOT_ENABLED = 2;
+
+ /**
+ * Dump device-specific state into the given file descriptors.
+ *
+ * One file descriptor must be passed to this method but two may be passed:
+ * the first descriptor must be used to dump device-specific state in text
+ * format, the second descriptor is optional and may be used to dump
+ * device-specific state in binary format.
+ *
+ * DumpstateMode can be used to limit the information that is output.
+ * For an example of when this is relevant, consider a bug report being generated with
+ * DumpstateMode::CONNECTIVITY - there is no reason to include camera or USB logs in this type
+ * of report.
+ *
+ * When verbose logging is disabled, getVerboseLoggingEnabled returns false, and this
+ * API is called, it may still output essential information but must not include
+ * information that identifies the user.
+ *
+ * @param fd array of file descriptors, with one or two valid file descriptors. The first FD is
+ * for text output, the second (if present) is for binary output.
+ * @param mode A mode value to restrict dumped content.
+ * @param timeoutMillis An approximate "budget" for how much time this call has been allotted.
+ * If execution runs longer than this, the IDumpstateDevice service may be killed and only
+ * partial information will be included in the report.
+ * @return If error, return service specific error with code
+ * ERROR_UNSUPPORTED_MODE or ERROR_DEVICE_LOGGING_NOT_ENABLED
+ */
+ void dumpstateBoard(in ParcelFileDescriptor[] fd, in DumpstateMode mode, in long timeoutMillis);
+
+ /**
+ * Queries the current state of verbose device logging. Primarily for UI and informative
+ * purposes.
+ *
+ * Even if verbose logging has been disabled, dumpstateBoard may still be called by the
+ * dumpstate routine, and essential information that does not identify the user may be included.
+ *
+ * @return Whether or not verbose vendor logging is currently enabled.
+ */
+ boolean getVerboseLoggingEnabled();
+
+ /**
+ * Turns verbose device vendor logging on or off.
+ *
+ * The setting should be persistent across reboots. Underlying implementations may need to start
+ * vendor logging daemons, set system properties, or change logging masks, for example. Given
+ * that many vendor logs contain significant amounts of private information and may come with
+ * memory/storage/battery impacts, calling this method on a user build should only be done after
+ * user consent has been obtained, e.g. from a toggle in developer settings.
+ *
+ * Even if verbose logging has been disabled, dumpstateBoard may still be called by the
+ * dumpstate routine, and essential information that does not identify the user may be included.
+ *
+ * @param enable Whether to enable or disable verbose vendor logging.
+ */
+ void setVerboseLoggingEnabled(in boolean enable);
+}
diff --git a/dumpstate/aidl/default/Android.bp b/dumpstate/aidl/default/Android.bp
new file mode 100644
index 0000000..45fdc17
--- /dev/null
+++ b/dumpstate/aidl/default/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2021 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.dumpstate-service.example",
+ relative_install_path: "hw",
+ init_rc: ["dumpstate-default.rc"],
+ vintf_fragments: ["dumpstate-default.xml"],
+ vendor: true,
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libdumpstateutil",
+ "liblog",
+ "libutils",
+ "android.hardware.dumpstate-V1-ndk",
+ ],
+ srcs: [
+ "main.cpp",
+ "Dumpstate.cpp",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"android.hardware.dumpstate-service.example\"",
+ ],
+}
diff --git a/dumpstate/aidl/default/Dumpstate.cpp b/dumpstate/aidl/default/Dumpstate.cpp
new file mode 100644
index 0000000..a0730fb
--- /dev/null
+++ b/dumpstate/aidl/default/Dumpstate.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/properties.h>
+#include <log/log.h>
+#include "DumpstateUtil.h"
+
+#include "Dumpstate.h"
+
+using android::os::dumpstate::DumpFileToFd;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace dumpstate {
+
+const char kVerboseLoggingProperty[] = "persist.dumpstate.verbose_logging.enabled";
+
+ndk::ScopedAStatus Dumpstate::dumpstateBoard(const std::vector<::ndk::ScopedFileDescriptor>& in_fds,
+ IDumpstateDevice::DumpstateMode in_mode,
+ int64_t in_timeoutMillis) {
+ (void)in_timeoutMillis;
+
+ if (in_fds.size() < 1) {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "No file descriptor");
+ }
+
+ int fd = in_fds[0].get();
+ if (fd < 0) {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Invalid file descriptor");
+ }
+
+ switch (in_mode) {
+ case IDumpstateDevice::DumpstateMode::FULL:
+ return dumpstateBoardImpl(fd, true);
+
+ case IDumpstateDevice::DumpstateMode::DEFAULT:
+ return dumpstateBoardImpl(fd, false);
+
+ case IDumpstateDevice::DumpstateMode::INTERACTIVE:
+ case IDumpstateDevice::DumpstateMode::REMOTE:
+ case IDumpstateDevice::DumpstateMode::WEAR:
+ case IDumpstateDevice::DumpstateMode::CONNECTIVITY:
+ case IDumpstateDevice::DumpstateMode::WIFI:
+ case IDumpstateDevice::DumpstateMode::PROTO:
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(ERROR_UNSUPPORTED_MODE,
+ "Unsupported mode");
+
+ default:
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Invalid mode");
+ }
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Dumpstate::getVerboseLoggingEnabled(bool* _aidl_return) {
+ *_aidl_return = getVerboseLoggingEnabledImpl();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Dumpstate::setVerboseLoggingEnabled(bool in_enable) {
+ ::android::base::SetProperty(kVerboseLoggingProperty, in_enable ? "true" : "false");
+ return ndk::ScopedAStatus::ok();
+}
+
+bool Dumpstate::getVerboseLoggingEnabledImpl() {
+ return ::android::base::GetBoolProperty(kVerboseLoggingProperty, false);
+}
+
+ndk::ScopedAStatus Dumpstate::dumpstateBoardImpl(const int fd, const bool full) {
+ ALOGD("DumpstateDevice::dumpstateBoard() FD: %d\n", fd);
+
+ dprintf(fd, "verbose logging: %s\n", getVerboseLoggingEnabledImpl() ? "enabled" : "disabled");
+ dprintf(fd, "[%s] %s\n", (full ? "full" : "default"), "Hello, world!");
+
+ // Shows an example on how to use the libdumpstateutil API.
+ DumpFileToFd(fd, "cmdline", "/proc/self/cmdline");
+
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace dumpstate
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/dumpstate/aidl/default/Dumpstate.h b/dumpstate/aidl/default/Dumpstate.h
new file mode 100644
index 0000000..0629831
--- /dev/null
+++ b/dumpstate/aidl/default/Dumpstate.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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/dumpstate/BnDumpstateDevice.h>
+#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
+#include <android/binder_status.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace dumpstate {
+
+class Dumpstate : public BnDumpstateDevice {
+ private:
+ bool getVerboseLoggingEnabledImpl();
+ ::ndk::ScopedAStatus dumpstateBoardImpl(const int fd, const bool full);
+
+ public:
+ ::ndk::ScopedAStatus dumpstateBoard(const std::vector<::ndk::ScopedFileDescriptor>& in_fds,
+ IDumpstateDevice::DumpstateMode in_mode,
+ int64_t in_timeoutMillis) override;
+
+ ::ndk::ScopedAStatus getVerboseLoggingEnabled(bool* _aidl_return) override;
+
+ ::ndk::ScopedAStatus setVerboseLoggingEnabled(bool in_enable) override;
+};
+
+} // namespace dumpstate
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/dumpstate/aidl/default/dumpstate-default.rc b/dumpstate/aidl/default/dumpstate-default.rc
new file mode 100644
index 0000000..4d011dd
--- /dev/null
+++ b/dumpstate/aidl/default/dumpstate-default.rc
@@ -0,0 +1,7 @@
+service vendor.dumpstate-default /vendor/bin/hw/android.hardware.dumpstate-service.example
+ class hal
+ user nobody
+ group nobody
+ interface aidl android.hardware.dumpstate.IDumpstateDevice/default
+ oneshot
+ disabled
diff --git a/dumpstate/aidl/default/dumpstate-default.xml b/dumpstate/aidl/default/dumpstate-default.xml
new file mode 100644
index 0000000..877aeed
--- /dev/null
+++ b/dumpstate/aidl/default/dumpstate-default.xml
@@ -0,0 +1,8 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.dumpstate</name>
+ <version>1</version>
+ <fqname>IDumpstateDevice/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/dumpstate/aidl/default/main.cpp b/dumpstate/aidl/default/main.cpp
new file mode 100644
index 0000000..2451752
--- /dev/null
+++ b/dumpstate/aidl/default/main.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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 "Dumpstate.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::dumpstate::Dumpstate;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ std::shared_ptr<Dumpstate> dumpstate = ndk::SharedRefBase::make<Dumpstate>();
+
+ const std::string instance = std::string() + Dumpstate::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_registerLazyService(dumpstate->asBinder().get(), instance.c_str());
+ CHECK(status == STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // Unreachable
+}
diff --git a/dumpstate/aidl/vts/functional/Android.bp b/dumpstate/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..5e516cf
--- /dev/null
+++ b/dumpstate/aidl/vts/functional/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2021 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: "VtsHalDumpstateTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalDumpstateTargetTest.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ "libvintf",
+ ],
+ static_libs: [
+ "android.hardware.dumpstate-V1-ndk",
+ ],
+ test_suites: [
+ "vts",
+ ],
+}
diff --git a/dumpstate/aidl/vts/functional/VtsHalDumpstateTargetTest.cpp b/dumpstate/aidl/vts/functional/VtsHalDumpstateTargetTest.cpp
new file mode 100644
index 0000000..442b0b0
--- /dev/null
+++ b/dumpstate/aidl/vts/functional/VtsHalDumpstateTargetTest.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2021 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 <fcntl.h>
+#include <unistd.h>
+
+#include <functional>
+#include <tuple>
+#include <vector>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::dumpstate::IDumpstateDevice;
+
+// Base class common to all dumpstate HAL AIDL tests.
+template <typename T>
+class DumpstateAidlTestBase : public ::testing::TestWithParam<T> {
+ protected:
+ bool CheckStatus(const ndk::ScopedAStatus& status, const binder_exception_t expected_ex_code,
+ const int32_t expected_service_specific) {
+ binder_exception_t ex_code = status.getExceptionCode();
+ if (ex_code != expected_ex_code) {
+ return false;
+ }
+ if (ex_code == EX_SERVICE_SPECIFIC) {
+ int32_t service_specific = status.getServiceSpecificError();
+ if (service_specific != expected_service_specific) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public:
+ virtual void SetUp() override { GetService(); }
+
+ virtual std::string GetInstanceName() = 0;
+
+ void GetService() {
+ const std::string instance_name = GetInstanceName();
+
+ ASSERT_TRUE(AServiceManager_isDeclared(instance_name.c_str()));
+ auto dumpstateBinder =
+ ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str()));
+ dumpstate = IDumpstateDevice::fromBinder(dumpstateBinder);
+ ASSERT_NE(dumpstate, nullptr) << "Could not get AIDL instance " << instance_name;
+ }
+
+ void ToggleVerboseLogging(bool enable) {
+ ndk::ScopedAStatus status;
+ bool logging_enabled = false;
+
+ status = dumpstate->setVerboseLoggingEnabled(enable);
+ ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.getDescription();
+
+ status = dumpstate->getVerboseLoggingEnabled(&logging_enabled);
+ ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.getDescription();
+ ASSERT_EQ(logging_enabled, enable)
+ << "Verbose logging should now be " << (enable ? "enabled" : "disabled");
+ }
+
+ void EnableVerboseLogging() { ToggleVerboseLogging(true); }
+
+ void DisableVerboseLogging() { ToggleVerboseLogging(false); }
+
+ std::shared_ptr<IDumpstateDevice> dumpstate;
+};
+
+// Tests that don't need to iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateAidlGeneralTest : public DumpstateAidlTestBase<std::string> {
+ protected:
+ virtual std::string GetInstanceName() override { return GetParam(); }
+};
+
+// Tests that iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateAidlPerModeTest
+ : public DumpstateAidlTestBase<std::tuple<std::string, IDumpstateDevice::DumpstateMode>> {
+ protected:
+ virtual std::string GetInstanceName() override { return std::get<0>(GetParam()); }
+
+ IDumpstateDevice::DumpstateMode GetMode() { return std::get<1>(GetParam()); }
+
+ // Will only execute additional_assertions when status == expected.
+ void AssertStatusForMode(const ::ndk::ScopedAStatus& status,
+ binder_exception_t expected_ex_code, int32_t expected_service_specific,
+ std::function<void()> additional_assertions = nullptr) {
+ if (GetMode() == IDumpstateDevice::DumpstateMode::DEFAULT) {
+ ASSERT_TRUE(CheckStatus(status, expected_ex_code, expected_ex_code));
+ } else {
+ // The rest of the modes are optional to support, but they MUST return either the
+ // expected value or UNSUPPORTED_MODE.
+ ASSERT_TRUE(CheckStatus(status, expected_ex_code, expected_service_specific) ||
+ CheckStatus(status, EX_SERVICE_SPECIFIC,
+ IDumpstateDevice::ERROR_UNSUPPORTED_MODE));
+ }
+ if (CheckStatus(status, expected_ex_code, expected_service_specific) &&
+ additional_assertions != nullptr) {
+ additional_assertions();
+ }
+ }
+};
+
+constexpr uint64_t kDefaultTimeoutMillis = 30 * 1000; // 30 seconds
+
+// Negative test: make sure dumpstateBoard() doesn't crash when passed a empty file descriptor
+// array.
+TEST_P(DumpstateAidlPerModeTest, TestNullHandle) {
+ EnableVerboseLogging();
+
+ std::vector<::ndk::ScopedFileDescriptor> dumpstateFds; // empty file descriptor vector
+
+ auto status = dumpstate->dumpstateBoard(dumpstateFds, GetMode(), kDefaultTimeoutMillis);
+ AssertStatusForMode(status, EX_ILLEGAL_ARGUMENT, 0);
+}
+
+// Positive test: make sure dumpstateBoard() writes something to the FD.
+TEST_P(DumpstateAidlPerModeTest, TestOk) {
+ EnableVerboseLogging();
+
+ // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+ int fds[2];
+ ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+ std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+ dumpstateFds.emplace_back(fds[1]);
+
+ auto status = dumpstate->dumpstateBoard(dumpstateFds, GetMode(), kDefaultTimeoutMillis);
+
+ AssertStatusForMode(status, EX_NONE, 0, [&fds]() {
+ // Check that at least one byte was written.
+ char buff;
+ ASSERT_EQ(1, read(fds[0], &buff, 1)) << "Dumped nothing";
+ });
+
+ close(fds[1]);
+ close(fds[0]);
+}
+
+// Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
+TEST_P(DumpstateAidlPerModeTest, TestHandleWithTwoFds) {
+ EnableVerboseLogging();
+
+ int fds1[2];
+ int fds2[2];
+ ASSERT_EQ(0, pipe2(fds1, O_NONBLOCK)) << errno;
+ ASSERT_EQ(0, pipe2(fds2, O_NONBLOCK)) << errno;
+
+ std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+ dumpstateFds.emplace_back(fds1[1]);
+ dumpstateFds.emplace_back(fds2[1]);
+
+ auto status = dumpstate->dumpstateBoard(dumpstateFds, GetMode(), kDefaultTimeoutMillis);
+
+ AssertStatusForMode(status, EX_NONE, 0, [&fds1, &fds2]() {
+ // Check that at least one byte was written to one of the FDs.
+ char buff;
+ size_t read1 = read(fds1[0], &buff, 1);
+ size_t read2 = read(fds2[0], &buff, 1);
+ // Sometimes read returns -1, so we can't just add them together and expect >= 1.
+ ASSERT_TRUE(read1 == 1 || read2 == 1) << "Dumped nothing";
+ });
+
+ close(fds1[1]);
+ close(fds1[0]);
+ close(fds2[1]);
+ close(fds2[0]);
+}
+
+// Make sure dumpstateBoard actually validates its arguments.
+TEST_P(DumpstateAidlGeneralTest, TestInvalidModeArgument_Negative) {
+ EnableVerboseLogging();
+
+ int fds[2];
+ ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+ std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+ dumpstateFds.emplace_back(fds[1]);
+
+ auto status = dumpstate->dumpstateBoard(dumpstateFds,
+ static_cast<IDumpstateDevice::DumpstateMode>(-100),
+ kDefaultTimeoutMillis);
+ ASSERT_TRUE(CheckStatus(status, EX_ILLEGAL_ARGUMENT, 0));
+
+ close(fds[1]);
+ close(fds[0]);
+}
+
+TEST_P(DumpstateAidlGeneralTest, TestInvalidModeArgument_Undefined) {
+ EnableVerboseLogging();
+
+ int fds[2];
+ ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+ std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+ dumpstateFds.emplace_back(fds[1]);
+
+ auto status = dumpstate->dumpstateBoard(dumpstateFds,
+ static_cast<IDumpstateDevice::DumpstateMode>(9001),
+ kDefaultTimeoutMillis);
+ ASSERT_TRUE(CheckStatus(status, EX_ILLEGAL_ARGUMENT, 0));
+
+ close(fds[1]);
+ close(fds[0]);
+}
+
+// Make sure disabling verbose logging behaves correctly. Some info is still allowed to be emitted,
+// but it can't have privacy/storage/battery impacts.
+TEST_P(DumpstateAidlPerModeTest, TestDeviceLoggingDisabled) {
+ DisableVerboseLogging();
+
+ // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+ int fds[2];
+ ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+ std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+ dumpstateFds.emplace_back(fds[1]);
+
+ auto status = dumpstate->dumpstateBoard(dumpstateFds, GetMode(), kDefaultTimeoutMillis);
+
+ // We don't include additional assertions here about the file passed in. If verbose logging is
+ // disabled, the OEM may choose to include nothing at all, but it is allowed to include some
+ // essential information based on the mode as long as it isn't private user information.
+ AssertStatusForMode(status, EX_NONE, 0);
+
+ close(fds[1]);
+ close(fds[0]);
+}
+
+// Double-enable is perfectly valid, but the second call shouldn't do anything.
+TEST_P(DumpstateAidlGeneralTest, TestRepeatedEnable) {
+ EnableVerboseLogging();
+ EnableVerboseLogging();
+}
+
+// Double-disable is perfectly valid, but the second call shouldn't do anything.
+TEST_P(DumpstateAidlGeneralTest, TestRepeatedDisable) {
+ DisableVerboseLogging();
+ DisableVerboseLogging();
+}
+
+// Toggling in short order is perfectly valid.
+TEST_P(DumpstateAidlGeneralTest, TestRepeatedToggle) {
+ EnableVerboseLogging();
+ DisableVerboseLogging();
+ EnableVerboseLogging();
+ DisableVerboseLogging();
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DumpstateAidlGeneralTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, DumpstateAidlGeneralTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IDumpstateDevice::descriptor)),
+ android::PrintInstanceNameToString);
+
+// Includes the mode's name as part of the description string.
+static inline std::string PrintInstanceNameToStringWithMode(
+ const testing::TestParamInfo<std::tuple<std::string, IDumpstateDevice::DumpstateMode>>&
+ info) {
+ return android::PrintInstanceNameToString(
+ testing::TestParamInfo(std::get<0>(info.param), info.index)) +
+ "_" + toString(std::get<1>(info.param));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DumpstateAidlPerModeTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstanceAndMode, DumpstateAidlPerModeTest,
+ testing::Combine(
+ testing::ValuesIn(android::getAidlHalInstanceNames(IDumpstateDevice::descriptor)),
+ testing::ValuesIn(ndk::internal::enum_values<IDumpstateDevice::DumpstateMode>)),
+ PrintInstanceNameToStringWithMode);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index 51295a6..4faf84b 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -43,6 +43,7 @@
"libmath",
"libnativewindow",
"librenderengine",
+ "libshaders",
"libtonemap",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@3.0-vts",
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 79ed368..1e0a329 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -67,6 +67,7 @@
"android.hardware.graphics.mapper@4.0-vts",
"libgtest",
"librenderengine",
+ "libshaders",
"libtonemap",
],
header_libs: [
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
index 2d23b08..b9460c8 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -40,6 +40,9 @@
using namespace std::chrono_literals;
+using ::android::GraphicBuffer;
+using ::android::sp;
+
class VtsDisplay {
public:
VtsDisplay(int64_t displayId, int32_t displayWidth, int32_t displayHeight)
@@ -73,40 +76,117 @@
ASSERT_NO_FATAL_FAILURE(mComposer = IComposer::fromBinder(binder));
ASSERT_NE(mComposer, nullptr);
ASSERT_NO_FATAL_FAILURE(mComposer->createClient(&mComposerClient));
- mInvalidDisplayId = GetInvalidDisplayId();
mComposerCallback = ::ndk::SharedRefBase::make<GraphicsComposerCallback>();
EXPECT_TRUE(mComposerClient->registerCallback(mComposerCallback).isOk());
// assume the first displays are built-in and are never removed
mDisplays = waitForDisplays();
-
mPrimaryDisplay = mDisplays[0].get();
+ ASSERT_NO_FATAL_FAILURE(mInvalidDisplayId = GetInvalidDisplayId());
+
+ int32_t activeConfig;
+ EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &activeConfig).isOk());
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+ DisplayAttribute::WIDTH, &mDisplayWidth)
+ .isOk());
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+ DisplayAttribute::HEIGHT, &mDisplayHeight)
+ .isOk());
// explicitly disable vsync
for (const auto& display : mDisplays) {
EXPECT_TRUE(mComposerClient->setVsyncEnabled(display.get(), false).isOk());
}
mComposerCallback->setVsyncAllowed(false);
-
- mWriter = std::make_unique<CommandWriterBase>(1024);
- mReader = std::make_unique<TestCommandReader>();
}
void TearDown() override {
- ASSERT_EQ(0, mReader->mErrors.size());
- ASSERT_EQ(0, mReader->mCompositionChanges.size());
-
+ destroyAllLayers();
if (mComposerCallback != nullptr) {
EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
- EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
EXPECT_EQ(0, mComposerCallback->getInvalidVsyncPeriodChangeCount());
EXPECT_EQ(0, mComposerCallback->getInvalidSeamlessPossibleCount());
}
}
+ void Test_setContentTypeForDisplay(const int64_t& display,
+ const std::vector<ContentType>& capabilities,
+ const ContentType& contentType, const char* contentTypeStr) {
+ const bool contentTypeSupport = std::find(capabilities.begin(), capabilities.end(),
+ contentType) != capabilities.end();
+
+ if (!contentTypeSupport) {
+ EXPECT_EQ(IComposerClient::EX_UNSUPPORTED,
+ mComposerClient->setContentType(display, contentType)
+ .getServiceSpecificError());
+ GTEST_SUCCEED() << contentTypeStr << " content type is not supported on display "
+ << std::to_string(display) << ", skipping test";
+ return;
+ }
+
+ EXPECT_TRUE(mComposerClient->setContentType(display, contentType).isOk());
+ EXPECT_TRUE(mComposerClient->setContentType(display, ContentType::NONE).isOk());
+ }
+
+ void Test_setContentType(const ContentType& contentType, const char* contentTypeStr) {
+ for (const auto& display : mDisplays) {
+ std::vector<ContentType> supportedContentTypes;
+ const auto error = mComposerClient->getSupportedContentTypes(display.get(),
+ &supportedContentTypes);
+ EXPECT_TRUE(error.isOk());
+
+ Test_setContentTypeForDisplay(display.get(), supportedContentTypes, contentType,
+ contentTypeStr);
+ }
+ }
+
+ int64_t createLayer(const VtsDisplay& display) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(display.get(), kBufferSlotCount, &layer).isOk());
+
+ auto resourceIt = mDisplayResources.find(display.get());
+ if (resourceIt == mDisplayResources.end()) {
+ resourceIt = mDisplayResources.insert({display.get(), DisplayResource(false)}).first;
+ }
+
+ EXPECT_TRUE(resourceIt->second.layers.insert(layer).second)
+ << "duplicated layer id " << layer;
+
+ return layer;
+ }
+
+ void destroyAllLayers() {
+ for (const auto& it : mDisplayResources) {
+ auto display = it.first;
+ const DisplayResource& resource = it.second;
+
+ for (auto layer : resource.layers) {
+ const auto error = mComposerClient->destroyLayer(display, layer);
+ EXPECT_TRUE(error.isOk());
+ }
+
+ if (resource.isVirtual) {
+ const auto error = mComposerClient->destroyVirtualDisplay(display);
+ EXPECT_TRUE(error.isOk());
+ }
+ }
+ mDisplayResources.clear();
+ }
+
+ void destroyLayer(const VtsDisplay& display, int64_t layer) {
+ auto const error = mComposerClient->destroyLayer(display.get(), layer);
+ ASSERT_TRUE(error.isOk()) << "failed to destroy layer " << layer;
+
+ auto resourceIt = mDisplayResources.find(display.get());
+ ASSERT_NE(mDisplayResources.end(), resourceIt);
+ resourceIt->second.layers.erase(layer);
+ }
+
// returns an invalid display id (one that has not been registered to a
// display. Currently assuming that a device will never have close to
// std::numeric_limit<uint64_t>::max() displays registered while running tests
@@ -120,7 +200,11 @@
id--;
}
- return 0;
+ // Although 0 could be an invalid display, a return value of 0
+ // from GetInvalidDisplayId means all other ids are in use, a condition which
+ // we are assuming a device will never have
+ EXPECT_NE(0, id);
+ return id;
}
std::vector<VtsDisplay> waitForDisplays() {
@@ -179,313 +263,11 @@
return error;
}
- void Test_setContentTypeForDisplay(const int64_t& display,
- const std::vector<ContentType>& capabilities,
- const ContentType& contentType, const char* contentTypeStr) {
- const bool contentTypeSupport = std::find(capabilities.begin(), capabilities.end(),
- contentType) != capabilities.end();
-
- if (!contentTypeSupport) {
- EXPECT_EQ(IComposerClient::EX_UNSUPPORTED,
- mComposerClient->setContentType(display, contentType)
- .getServiceSpecificError());
- GTEST_SUCCEED() << contentTypeStr << " content type is not supported on display "
- << std::to_string(display) << ", skipping test";
- return;
- }
-
- EXPECT_TRUE(mComposerClient->setContentType(display, contentType).isOk());
- EXPECT_TRUE(mComposerClient->setContentType(display, ContentType::NONE).isOk());
- }
-
- void Test_setContentType(const ContentType& contentType, const char* contentTypeStr) {
- for (const auto& display : mDisplays) {
- std::vector<ContentType> supportedContentTypes;
- const auto error = mComposerClient->getSupportedContentTypes(display.get(),
- &supportedContentTypes);
- EXPECT_TRUE(error.isOk());
-
- Test_setContentTypeForDisplay(display.get(), supportedContentTypes, contentType,
- contentTypeStr);
- }
- }
-
- void execute() {
- TestCommandReader* reader = mReader.get();
- CommandWriterBase* writer = mWriter.get();
- bool queueChanged = false;
- int32_t commandLength = 0;
- std::vector<NativeHandle> commandHandles;
- ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
-
- if (queueChanged) {
- auto ret = mComposerClient->setInputCommandQueue(writer->getMQDescriptor());
- ASSERT_TRUE(ret.isOk());
- }
-
- ExecuteCommandsStatus commandStatus;
- EXPECT_TRUE(mComposerClient->executeCommands(commandLength, commandHandles, &commandStatus)
- .isOk());
-
- if (commandStatus.queueChanged) {
- MQDescriptor<int32_t, SynchronizedReadWrite> outputCommandQueue;
- ASSERT_TRUE(mComposerClient->getOutputCommandQueue(&outputCommandQueue).isOk());
- reader->setMQDescriptor(outputCommandQueue);
- }
- ASSERT_TRUE(reader->readQueue(commandStatus.length, std::move(commandStatus.handles)));
- reader->parse();
- reader->reset();
- writer->reset();
- }
-
- ::android::sp<::android::GraphicBuffer> allocate(uint32_t width, uint32_t height) {
- ::android::sp<::android::GraphicBuffer> buffer =
- ::android::sp<::android::GraphicBuffer>::make(
- width, height, ::android::PIXEL_FORMAT_RGBA_8888,
- /*layerCount*/ 1,
- static_cast<uint64_t>(
- static_cast<int>(common::BufferUsage::CPU_WRITE_OFTEN) |
- static_cast<int>(common::BufferUsage::CPU_READ_OFTEN)),
- "VtsHalGraphicsComposer3_TargetTest");
-
- return buffer;
- }
-
struct TestParameters {
nsecs_t delayForChange;
bool refreshMiss;
};
- static inline auto toTimePoint(nsecs_t time) {
- return std::chrono::time_point<std::chrono::steady_clock>(std::chrono::nanoseconds(time));
- }
-
- int64_t createLayer(const VtsDisplay& display) {
- int64_t layer;
- EXPECT_TRUE(mComposerClient->createLayer(display.get(), kBufferSlotCount, &layer).isOk());
-
- auto resourceIt = mDisplayResources.find(display.get());
- if (resourceIt == mDisplayResources.end()) {
- resourceIt = mDisplayResources.insert({display.get(), DisplayResource(false)}).first;
- }
-
- EXPECT_TRUE(resourceIt->second.layers.insert(layer).second)
- << "duplicated layer id " << layer;
-
- return layer;
- }
-
- void destroyLayer(const VtsDisplay& display, int64_t layer) {
- auto const error = mComposerClient->destroyLayer(display.get(), layer);
- ASSERT_TRUE(error.isOk()) << "failed to destroy layer " << layer;
-
- auto resourceIt = mDisplayResources.find(display.get());
- ASSERT_NE(mDisplayResources.end(), resourceIt);
- resourceIt->second.layers.erase(layer);
- }
-
- void forEachTwoConfigs(int64_t display, std::function<void(int32_t, int32_t)> func) {
- std::vector<int32_t> displayConfigs;
- EXPECT_TRUE(mComposerClient->getDisplayConfigs(display, &displayConfigs).isOk());
- for (const int32_t config1 : displayConfigs) {
- for (const int32_t config2 : displayConfigs) {
- if (config1 != config2) {
- func(config1, config2);
- }
- }
- }
- }
-
- void setActiveConfig(VtsDisplay& display, int32_t config) {
- EXPECT_TRUE(mComposerClient->setActiveConfig(display.get(), config).isOk());
- int32_t displayWidth;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config, DisplayAttribute::WIDTH,
- &displayWidth)
- .isOk());
- int32_t displayHeight;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config, DisplayAttribute::HEIGHT,
- &displayHeight)
- .isOk());
- display.setDimensions(displayWidth, displayHeight);
- }
-
- void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline* timeline) {
- if (timeline != nullptr) {
- // Refresh time should be before newVsyncAppliedTimeNanos
- EXPECT_LT(timeline->refreshTimeNanos, timeline->newVsyncAppliedTimeNanos);
-
- std::this_thread::sleep_until(toTimePoint(timeline->refreshTimeNanos));
- }
-
- mWriter->selectDisplay(display.get());
- EXPECT_TRUE(mComposerClient->setPowerMode(display.get(), PowerMode::ON).isOk());
- EXPECT_TRUE(
- mComposerClient
- ->setColorMode(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC)
- .isOk());
-
- FRect displayCrop = display.getCrop();
- auto displayWidth = static_cast<uint32_t>(std::ceilf(displayCrop.right - displayCrop.left));
- auto displayHeight =
- static_cast<uint32_t>(std::ceilf(displayCrop.bottom - displayCrop.top));
- int64_t layer = 0;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer(display));
- {
- auto buffer = allocate(displayWidth, displayHeight);
- ASSERT_NE(nullptr, buffer);
- ASSERT_EQ(::android::OK, buffer->initCheck());
- ASSERT_NE(nullptr, buffer->handle);
-
- mWriter->selectLayer(layer);
- mWriter->setLayerCompositionType(Composition::DEVICE);
- mWriter->setLayerDisplayFrame(display.getFrameRect());
- mWriter->setLayerPlaneAlpha(1);
- mWriter->setLayerSourceCrop(display.getCrop());
- mWriter->setLayerTransform(static_cast<Transform>(0));
- mWriter->setLayerVisibleRegion(std::vector<Rect>(1, display.getFrameRect()));
- mWriter->setLayerZOrder(10);
- mWriter->setLayerBlendMode(BlendMode::NONE);
- mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, display.getFrameRect()));
- mWriter->setLayerBuffer(0, buffer->handle, -1);
- mWriter->setLayerDataspace(common::Dataspace::UNKNOWN);
-
- mWriter->validateDisplay();
- execute();
- ASSERT_EQ(0, mReader->mErrors.size());
- mReader->mCompositionChanges.clear();
-
- mWriter->presentDisplay();
- execute();
- ASSERT_EQ(0, mReader->mErrors.size());
- }
-
- {
- auto buffer = allocate(displayWidth, displayHeight);
- ASSERT_NE(nullptr, buffer->handle);
-
- mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(0, buffer->handle, -1);
- mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, {0, 0, 10, 10}));
- mWriter->validateDisplay();
- execute();
- ASSERT_EQ(0, mReader->mErrors.size());
- mReader->mCompositionChanges.clear();
-
- mWriter->presentDisplay();
- execute();
- }
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
- }
-
- void waitForVsyncPeriodChange(int64_t display, const VsyncPeriodChangeTimeline& timeline,
- int64_t desiredTimeNanos, int64_t oldPeriodNanos,
- int64_t newPeriodNanos) {
- const auto kChangeDeadline = toTimePoint(timeline.newVsyncAppliedTimeNanos) + 100ms;
- while (std::chrono::steady_clock::now() <= kChangeDeadline) {
- int32_t vsyncPeriodNanos;
- EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos).isOk());
- if (systemTime() <= desiredTimeNanos) {
- EXPECT_EQ(vsyncPeriodNanos, oldPeriodNanos);
- } else if (vsyncPeriodNanos == newPeriodNanos) {
- break;
- }
- std::this_thread::sleep_for(std::chrono::nanoseconds(oldPeriodNanos));
- }
- }
-
- void Test_setActiveConfigWithConstraints(const TestParameters& params) {
- for (VtsDisplay& display : mDisplays) {
- forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) {
- setActiveConfig(display, config1);
- sendRefreshFrame(display, nullptr);
-
- int32_t vsyncPeriod1;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config1,
- DisplayAttribute::VSYNC_PERIOD,
- &vsyncPeriod1)
- .isOk());
- int32_t configGroup1;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config1,
- DisplayAttribute::CONFIG_GROUP,
- &configGroup1)
- .isOk());
- int32_t vsyncPeriod2;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config2,
- DisplayAttribute::VSYNC_PERIOD,
- &vsyncPeriod2)
- .isOk());
- int32_t configGroup2;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config2,
- DisplayAttribute::CONFIG_GROUP,
- &configGroup2)
- .isOk());
-
- if (vsyncPeriod1 == vsyncPeriod2) {
- return; // continue
- }
-
- // We don't allow delayed change when changing config groups
- if (params.delayForChange > 0 && configGroup1 != configGroup2) {
- return; // continue
- }
-
- VsyncPeriodChangeTimeline timeline;
- VsyncPeriodChangeConstraints constraints = {
- .desiredTimeNanos = systemTime() + params.delayForChange,
- .seamlessRequired = false};
- EXPECT_TRUE(setActiveConfigWithConstraints(display, config2, constraints, &timeline)
- .isOk());
-
- EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
- // Refresh rate should change within a reasonable time
- constexpr std::chrono::nanoseconds kReasonableTimeForChange = 1s; // 1 second
- EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
- kReasonableTimeForChange.count());
-
- if (timeline.refreshRequired) {
- if (params.refreshMiss) {
- // Miss the refresh frame on purpose to make sure the implementation sends a
- // callback
- std::this_thread::sleep_until(toTimePoint(timeline.refreshTimeNanos) +
- 100ms);
- }
- sendRefreshFrame(display, &timeline);
- }
- waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos,
- vsyncPeriod1, vsyncPeriod2);
-
- // At this point the refresh rate should have changed already, however in rare
- // cases the implementation might have missed the deadline. In this case a new
- // timeline should have been provided.
- auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
- if (timeline.refreshRequired && params.refreshMiss) {
- EXPECT_TRUE(newTimeline.has_value());
- }
-
- if (newTimeline.has_value()) {
- if (newTimeline->refreshRequired) {
- sendRefreshFrame(display, &newTimeline.value());
- }
- waitForVsyncPeriodChange(display.get(), newTimeline.value(),
- constraints.desiredTimeNanos, vsyncPeriod1,
- vsyncPeriod2);
- }
-
- int32_t vsyncPeriodNanos;
- EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
- .isOk());
- EXPECT_EQ(vsyncPeriodNanos, vsyncPeriod2);
- });
- }
- }
-
// Keep track of all virtual displays and layers. When a test fails with
// ASSERT_*, the destructor will clean up the resources for the test.
struct DisplayResource {
@@ -501,11 +283,11 @@
int64_t mPrimaryDisplay;
std::vector<VtsDisplay> mDisplays;
std::shared_ptr<GraphicsComposerCallback> mComposerCallback;
- std::unique_ptr<CommandWriterBase> mWriter;
- std::unique_ptr<TestCommandReader> mReader;
// use the slot count usually set by SF
static constexpr uint32_t kBufferSlotCount = 64;
std::unordered_map<int64_t, DisplayResource> mDisplayResources;
+ int32_t mDisplayWidth;
+ int32_t mDisplayHeight;
};
TEST_P(GraphicsComposerAidlTest, getDisplayCapabilitiesBadDisplay) {
@@ -524,102 +306,17 @@
}
}
-TEST_P(GraphicsComposerAidlTest, getDisplayVsyncPeriod) {
- for (VtsDisplay& display : mDisplays) {
- std::vector<int32_t> configs;
- EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
- for (int32_t config : configs) {
- int32_t expectedVsyncPeriodNanos = -1;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config,
- DisplayAttribute::VSYNC_PERIOD,
- &expectedVsyncPeriodNanos)
- .isOk());
-
- VsyncPeriodChangeTimeline timeline;
- VsyncPeriodChangeConstraints constraints;
-
- constraints.desiredTimeNanos = systemTime();
- constraints.seamlessRequired = false;
- EXPECT_TRUE(mComposerClient
- ->setActiveConfigWithConstraints(display.get(), config, constraints,
- &timeline)
- .isOk());
-
- if (timeline.refreshRequired) {
- sendRefreshFrame(display, &timeline);
- }
- waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos, 0,
- expectedVsyncPeriodNanos);
-
- int32_t vsyncPeriodNanos;
- int retryCount = 100;
- do {
- std::this_thread::sleep_for(10ms);
- vsyncPeriodNanos = 0;
- EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
- .isOk());
- --retryCount;
- } while (vsyncPeriodNanos != expectedVsyncPeriodNanos && retryCount > 0);
-
- EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
-
- // Make sure that the vsync period stays the same if the active config is not
- // changed.
- auto timeout = 1ms;
- for (int i = 0; i < 10; i++) {
- std::this_thread::sleep_for(timeout);
- timeout *= 2;
- vsyncPeriodNanos = 0;
- EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
- .isOk());
- EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
- }
- }
- }
+TEST_P(GraphicsComposerAidlTest, DumpDebugInfo) {
+ std::string debugInfo;
+ EXPECT_TRUE(mComposer->dumpDebugInfo(&debugInfo).isOk());
}
-TEST_P(GraphicsComposerAidlTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
- VsyncPeriodChangeTimeline timeline;
- VsyncPeriodChangeConstraints constraints;
+TEST_P(GraphicsComposerAidlTest, CreateClientSingleton) {
+ std::shared_ptr<IComposerClient> composerClient;
+ const auto error = mComposer->createClient(&composerClient);
- constraints.seamlessRequired = true;
- constraints.desiredTimeNanos = systemTime();
-
- for (VtsDisplay& display : mDisplays) {
- forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) {
- int32_t configGroup1;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config1,
- DisplayAttribute::CONFIG_GROUP, &configGroup1)
- .isOk());
- int32_t configGroup2;
- EXPECT_TRUE(mComposerClient
- ->getDisplayAttribute(display.get(), config2,
- DisplayAttribute::CONFIG_GROUP, &configGroup2)
- .isOk());
- if (configGroup1 != configGroup2) {
- setActiveConfig(display, config1);
- sendRefreshFrame(display, nullptr);
- EXPECT_EQ(IComposerClient::EX_SEAMLESS_NOT_ALLOWED,
- setActiveConfigWithConstraints(display, config2, constraints, &timeline)
- .getServiceSpecificError());
- }
- });
- }
-}
-
-TEST_P(GraphicsComposerAidlTest, setActiveConfigWithConstraints) {
- Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
-}
-
-TEST_P(GraphicsComposerAidlTest, setActiveConfigWithConstraints_Delayed) {
- Test_setActiveConfigWithConstraints({.delayForChange = 300'000'000, // 300ms
- .refreshMiss = false});
-}
-
-TEST_P(GraphicsComposerAidlTest, setActiveConfigWithConstraints_MissRefresh) {
- Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = true});
+ EXPECT_FALSE(error.isOk());
+ EXPECT_EQ(IComposerClient::EX_NO_RESOURCES, error.getServiceSpecificError());
}
TEST_P(GraphicsComposerAidlTest, GetDisplayIdentificationData) {
@@ -658,51 +355,6 @@
<< "data is not stable";
}
-TEST_P(GraphicsComposerAidlTest, SET_LAYER_PER_FRAME_METADATA) {
- int64_t layer;
- EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
-
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
-
- /**
- * DISPLAY_P3 is a color space that uses the DCI_P3 primaries,
- * the D65 white point and the SRGB transfer functions.
- * Rendering Intent: Colorimetric
- * Primaries:
- * x y
- * green 0.265 0.690
- * blue 0.150 0.060
- * red 0.680 0.320
- * white (D65) 0.3127 0.3290
- */
-
- std::vector<PerFrameMetadata> aidlMetadata;
- aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, 0.680f});
- aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, 0.320f});
- aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X, 0.265f});
- aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y, 0.690f});
- aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X, 0.150f});
- aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y, 0.060f});
- aidlMetadata.push_back({PerFrameMetadataKey::WHITE_POINT_X, 0.3127f});
- aidlMetadata.push_back({PerFrameMetadataKey::WHITE_POINT_Y, 0.3290f});
- aidlMetadata.push_back({PerFrameMetadataKey::MAX_LUMINANCE, 100.0f});
- aidlMetadata.push_back({PerFrameMetadataKey::MIN_LUMINANCE, 0.1f});
- aidlMetadata.push_back({PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, 78.0});
- aidlMetadata.push_back({PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0});
- mWriter->setLayerPerFrameMetadata(aidlMetadata);
- execute();
-
- if (mReader->mErrors.size() == 1 && mReader->mErrors[0].second == EX_UNSUPPORTED_OPERATION) {
- mReader->mErrors.clear();
- GTEST_SUCCEED() << "SetLayerPerFrameMetadata is not supported";
- EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
- return;
- }
-
- EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
-}
-
TEST_P(GraphicsComposerAidlTest, GetHdrCapabilities) {
HdrCapabilities hdrCapabilities;
const auto error = mComposerClient->getHdrCapabilities(mPrimaryDisplay, &hdrCapabilities);
@@ -816,11 +468,19 @@
}
TEST_P(GraphicsComposerAidlTest, SetColorModeBadDisplay) {
- auto const error = mComposerClient->setColorMode(mInvalidDisplayId, ColorMode::NATIVE,
- RenderIntent::COLORIMETRIC);
+ std::vector<ColorMode> colorModes;
+ EXPECT_TRUE(mComposerClient->getColorModes(mPrimaryDisplay, &colorModes).isOk());
+ for (auto mode : colorModes) {
+ std::vector<RenderIntent> intents;
+ EXPECT_TRUE(mComposerClient->getRenderIntents(mPrimaryDisplay, mode, &intents).isOk())
+ << "failed to get render intents";
+ for (auto intent : intents) {
+ auto const error = mComposerClient->setColorMode(mInvalidDisplayId, mode, intent);
- EXPECT_FALSE(error.isOk());
- ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+ EXPECT_FALSE(error.isOk());
+ ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+ }
+ }
}
TEST_P(GraphicsComposerAidlTest, SetColorModeBadParameter) {
@@ -837,31 +497,6 @@
EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, renderIntentError.getServiceSpecificError());
}
-TEST_P(GraphicsComposerAidlTest, SetLayerColorTransform) {
- int64_t layer;
- EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
-
- // clang-format off
- const std::array<float, 16> matrix = {{
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f,
- }};
- // clang-format on
-
- mWriter->setLayerColorTransform(matrix.data());
- execute();
-
- if (mReader->mErrors.size() == 1 && mReader->mErrors[0].second == EX_UNSUPPORTED_OPERATION) {
- mReader->mErrors.clear();
- GTEST_SUCCEED() << "setLayerColorTransform is not supported";
- return;
- }
-}
-
TEST_P(GraphicsComposerAidlTest, GetDisplayedContentSamplingAttributes) {
int constexpr invalid = -1;
@@ -1267,12 +902,158 @@
EXPECT_TRUE(mComposerClient->destroyVirtualDisplay(virtualDisplay.display).isOk());
}
+TEST_P(GraphicsComposerAidlTest, DestroyVirtualDisplayBadDisplay) {
+ int32_t maxDisplayCount = 0;
+ EXPECT_TRUE(mComposerClient->getMaxVirtualDisplayCount(&maxDisplayCount).isOk());
+ if (maxDisplayCount == 0) {
+ GTEST_SUCCEED() << "no virtual display support";
+ return;
+ }
+ const auto error = mComposerClient->destroyVirtualDisplay(mInvalidDisplayId);
+
+ EXPECT_FALSE(error.isOk());
+ ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, CreateLayer) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, CreateLayerBadDisplay) {
+ int64_t layer;
+ const auto error = mComposerClient->createLayer(mInvalidDisplayId, kBufferSlotCount, &layer);
+
+ EXPECT_FALSE(error.isOk());
+ ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, DestroyLayerBadDisplay) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ const auto error = mComposerClient->destroyLayer(mInvalidDisplayId, layer);
+
+ EXPECT_FALSE(error.isOk());
+ EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+ EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, DestroyLayerBadLayerError) {
+ // We haven't created any layers yet, so any id should be invalid
+ const auto error = mComposerClient->destroyLayer(mPrimaryDisplay, 1);
+
+ EXPECT_FALSE(error.isOk());
+ EXPECT_EQ(IComposerClient::EX_BAD_LAYER, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetActiveConfigBadDisplay) {
+ int32_t config;
+ const auto error = mComposerClient->getActiveConfig(mInvalidDisplayId, &config);
+
+ EXPECT_FALSE(error.isOk());
+ ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayConfig) {
+ std::vector<int32_t> configs;
+ EXPECT_TRUE(mComposerClient->getDisplayConfigs(mPrimaryDisplay, &configs).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayConfigBadDisplay) {
+ std::vector<int32_t> configs;
+ const auto error = mComposerClient->getDisplayConfigs(mInvalidDisplayId, &configs);
+
+ EXPECT_FALSE(error.isOk());
+ ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayName) {
+ std::string displayName;
+ EXPECT_TRUE(mComposerClient->getDisplayName(mPrimaryDisplay, &displayName).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, SetClientTargetSlotCount) {
+ EXPECT_TRUE(
+ mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, SetActiveConfig) {
+ std::vector<int32_t> configs;
+ EXPECT_TRUE(mComposerClient->getDisplayConfigs(mPrimaryDisplay, &configs).isOk());
+ for (auto config : configs) {
+ EXPECT_TRUE(mComposerClient->setActiveConfig(mPrimaryDisplay, config).isOk());
+ int32_t config1;
+ EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &config1).isOk());
+ EXPECT_EQ(config, config1);
+ }
+}
+
+TEST_P(GraphicsComposerAidlTest, SetActiveConfigPowerCycle) {
+ EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF).isOk());
+ EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON).isOk());
+
+ std::vector<int32_t> configs;
+ EXPECT_TRUE(mComposerClient->getDisplayConfigs(mPrimaryDisplay, &configs).isOk());
+ for (auto config : configs) {
+ EXPECT_TRUE(mComposerClient->setActiveConfig(mPrimaryDisplay, config).isOk());
+ int32_t config1;
+ EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &config1).isOk());
+ EXPECT_EQ(config, config1);
+
+ EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF).isOk());
+ EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON).isOk());
+ EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &config1).isOk());
+ EXPECT_EQ(config, config1);
+ }
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDozeSupportBadDisplay) {
+ bool isDozeSupport;
+ const auto error = mComposerClient->getDozeSupport(mInvalidDisplayId, &isDozeSupport);
+ EXPECT_FALSE(error.isOk());
+ ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, SetPowerModeUnsupported) {
+ bool isDozeSupported;
+ mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk();
+ if (!isDozeSupported) {
+ auto error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE);
+ EXPECT_FALSE(error.isOk());
+ EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+
+ error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE_SUSPEND);
+ EXPECT_FALSE(error.isOk());
+ EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+ }
+}
+
+TEST_P(GraphicsComposerAidlTest, SetVsyncEnabled) {
+ mComposerCallback->setVsyncAllowed(true);
+
+ EXPECT_TRUE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, true).isOk());
+ usleep(60 * 1000);
+ EXPECT_TRUE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false).isOk());
+
+ mComposerCallback->setVsyncAllowed(false);
+}
+
TEST_P(GraphicsComposerAidlTest, SetPowerMode) {
std::vector<PowerMode> modes;
modes.push_back(PowerMode::OFF);
modes.push_back(PowerMode::ON_SUSPEND);
modes.push_back(PowerMode::ON);
+ bool isDozeSupported;
+ EXPECT_TRUE(mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk());
+ if (isDozeSupported) {
+ modes.push_back(PowerMode::DOZE);
+ modes.push_back(PowerMode::DOZE_SUSPEND);
+ }
+
for (auto mode : modes) {
EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
}
@@ -1282,47 +1063,46 @@
std::vector<PowerMode> modes;
modes.push_back(PowerMode::OFF);
+ modes.push_back(PowerMode::ON);
modes.push_back(PowerMode::OFF);
-
for (auto mode : modes) {
EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
}
+ modes.clear();
+ modes.push_back(PowerMode::OFF);
+ modes.push_back(PowerMode::OFF);
+ for (auto mode : modes) {
+ EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+ }
modes.clear();
modes.push_back(PowerMode::ON);
modes.push_back(PowerMode::ON);
-
for (auto mode : modes) {
EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
}
-
modes.clear();
modes.push_back(PowerMode::ON_SUSPEND);
modes.push_back(PowerMode::ON_SUSPEND);
-
for (auto mode : modes) {
EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
}
+ modes.clear();
bool isDozeSupported = false;
ASSERT_TRUE(mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk());
if (isDozeSupported) {
- modes.clear();
-
modes.push_back(PowerMode::DOZE);
modes.push_back(PowerMode::DOZE);
-
for (auto mode : modes) {
EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
}
-
modes.clear();
modes.push_back(PowerMode::DOZE_SUSPEND);
modes.push_back(PowerMode::DOZE_SUSPEND);
-
for (auto mode : modes) {
EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
}
@@ -1343,20 +1123,6 @@
ASSERT_EQ(IComposerClient::EX_BAD_PARAMETER, error.getServiceSpecificError());
}
-TEST_P(GraphicsComposerAidlTest, SetPowerModeUnsupported) {
- bool isDozeSupported = false;
- EXPECT_TRUE(mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk());
- if (!isDozeSupported) {
- auto error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE);
- EXPECT_FALSE(error.isOk());
- EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
-
- error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE_SUSPEND);
- EXPECT_FALSE(error.isOk());
- EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
- }
-}
-
TEST_P(GraphicsComposerAidlTest, GetDataspaceSaturationMatrix) {
std::vector<float> matrix;
EXPECT_TRUE(
@@ -1379,6 +1145,774 @@
EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, error.getServiceSpecificError());
}
+// Tests for Command.
+class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest {
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(GraphicsComposerAidlTest::SetUp());
+
+ mWriter = std::make_unique<CommandWriterBase>(1024);
+ mReader = std::make_unique<TestCommandReader>();
+ }
+
+ void TearDown() override {
+ ASSERT_EQ(0, mReader->mErrors.size());
+ ASSERT_EQ(0, mReader->mCompositionChanges.size());
+ ASSERT_NO_FATAL_FAILURE(GraphicsComposerAidlTest::TearDown());
+ }
+
+ void execute() {
+ TestCommandReader* reader = mReader.get();
+ CommandWriterBase* writer = mWriter.get();
+ bool queueChanged = false;
+ int32_t commandLength = 0;
+ std::vector<NativeHandle> commandHandles;
+ ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
+
+ if (queueChanged) {
+ auto ret = mComposerClient->setInputCommandQueue(writer->getMQDescriptor());
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ ExecuteCommandsStatus commandStatus;
+ EXPECT_TRUE(mComposerClient->executeCommands(commandLength, commandHandles, &commandStatus)
+ .isOk());
+
+ if (commandStatus.queueChanged) {
+ MQDescriptor<int32_t, SynchronizedReadWrite> outputCommandQueue;
+ ASSERT_TRUE(mComposerClient->getOutputCommandQueue(&outputCommandQueue).isOk());
+ reader->setMQDescriptor(outputCommandQueue);
+ }
+ ASSERT_TRUE(reader->readQueue(commandStatus.length, std::move(commandStatus.handles)));
+ reader->parse();
+ reader->reset();
+ writer->reset();
+ }
+
+ static inline auto toTimePoint(nsecs_t time) {
+ return std::chrono::time_point<std::chrono::steady_clock>(std::chrono::nanoseconds(time));
+ }
+
+ void setActiveConfig(VtsDisplay& display, int32_t config) {
+ EXPECT_TRUE(mComposerClient->setActiveConfig(display.get(), config).isOk());
+ int32_t displayWidth;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config, DisplayAttribute::WIDTH,
+ &displayWidth)
+ .isOk());
+ int32_t displayHeight;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config, DisplayAttribute::HEIGHT,
+ &displayHeight)
+ .isOk());
+ display.setDimensions(displayWidth, displayHeight);
+ }
+
+ void forEachTwoConfigs(int64_t display, std::function<void(int32_t, int32_t)> func) {
+ std::vector<int32_t> displayConfigs;
+ EXPECT_TRUE(mComposerClient->getDisplayConfigs(display, &displayConfigs).isOk());
+ for (const int32_t config1 : displayConfigs) {
+ for (const int32_t config2 : displayConfigs) {
+ if (config1 != config2) {
+ func(config1, config2);
+ }
+ }
+ }
+ }
+
+ void waitForVsyncPeriodChange(int64_t display, const VsyncPeriodChangeTimeline& timeline,
+ int64_t desiredTimeNanos, int64_t oldPeriodNanos,
+ int64_t newPeriodNanos) {
+ const auto kChangeDeadline = toTimePoint(timeline.newVsyncAppliedTimeNanos) + 100ms;
+ while (std::chrono::steady_clock::now() <= kChangeDeadline) {
+ int32_t vsyncPeriodNanos;
+ EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos).isOk());
+ if (systemTime() <= desiredTimeNanos) {
+ EXPECT_EQ(vsyncPeriodNanos, oldPeriodNanos);
+ } else if (vsyncPeriodNanos == newPeriodNanos) {
+ break;
+ }
+ std::this_thread::sleep_for(std::chrono::nanoseconds(oldPeriodNanos));
+ }
+ }
+
+ sp<GraphicBuffer> allocate() {
+ return sp<GraphicBuffer>::make(
+ static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight),
+ ::android::PIXEL_FORMAT_RGBA_8888,
+ /*layerCount*/ 1,
+ (static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+ static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+ static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY)),
+ "VtsHalGraphicsComposer3_TargetTest");
+ }
+
+ void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline* timeline) {
+ if (timeline != nullptr) {
+ // Refresh time should be before newVsyncAppliedTimeNanos
+ EXPECT_LT(timeline->refreshTimeNanos, timeline->newVsyncAppliedTimeNanos);
+
+ std::this_thread::sleep_until(toTimePoint(timeline->refreshTimeNanos));
+ }
+
+ mWriter->selectDisplay(display.get());
+ EXPECT_TRUE(mComposerClient->setPowerMode(display.get(), PowerMode::ON).isOk());
+ EXPECT_TRUE(
+ mComposerClient
+ ->setColorMode(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC)
+ .isOk());
+
+ int64_t layer = 0;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer(display));
+ {
+ auto buffer = allocate();
+ ASSERT_NE(nullptr, buffer);
+ ASSERT_EQ(::android::OK, buffer->initCheck());
+ ASSERT_NE(nullptr, buffer->handle);
+
+ mWriter->selectLayer(layer);
+ mWriter->setLayerCompositionType(Composition::DEVICE);
+ mWriter->setLayerDisplayFrame(display.getFrameRect());
+ mWriter->setLayerPlaneAlpha(1);
+ mWriter->setLayerSourceCrop(display.getCrop());
+ mWriter->setLayerTransform(static_cast<Transform>(0));
+ mWriter->setLayerVisibleRegion(std::vector<Rect>(1, display.getFrameRect()));
+ mWriter->setLayerZOrder(10);
+ mWriter->setLayerBlendMode(BlendMode::NONE);
+ mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, display.getFrameRect()));
+ mWriter->setLayerBuffer(0, buffer->handle, -1);
+ mWriter->setLayerDataspace(common::Dataspace::UNKNOWN);
+
+ mWriter->validateDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mReader->mCompositionChanges.clear();
+
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ }
+
+ {
+ auto buffer = allocate();
+ ASSERT_NE(nullptr, buffer->handle);
+
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBuffer(0, buffer->handle, -1);
+ mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, {0, 0, 10, 10}));
+ mWriter->validateDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mReader->mCompositionChanges.clear();
+
+ mWriter->presentDisplay();
+ execute();
+ }
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+ }
+
+ void Test_setActiveConfigWithConstraints(const TestParameters& params) {
+ for (VtsDisplay& display : mDisplays) {
+ forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) {
+ setActiveConfig(display, config1);
+ sendRefreshFrame(display, nullptr);
+
+ int32_t vsyncPeriod1;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config1,
+ DisplayAttribute::VSYNC_PERIOD,
+ &vsyncPeriod1)
+ .isOk());
+ int32_t configGroup1;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config1,
+ DisplayAttribute::CONFIG_GROUP,
+ &configGroup1)
+ .isOk());
+ int32_t vsyncPeriod2;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config2,
+ DisplayAttribute::VSYNC_PERIOD,
+ &vsyncPeriod2)
+ .isOk());
+ int32_t configGroup2;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config2,
+ DisplayAttribute::CONFIG_GROUP,
+ &configGroup2)
+ .isOk());
+
+ if (vsyncPeriod1 == vsyncPeriod2) {
+ return; // continue
+ }
+
+ // We don't allow delayed change when changing config groups
+ if (params.delayForChange > 0 && configGroup1 != configGroup2) {
+ return; // continue
+ }
+
+ VsyncPeriodChangeTimeline timeline;
+ VsyncPeriodChangeConstraints constraints = {
+ .desiredTimeNanos = systemTime() + params.delayForChange,
+ .seamlessRequired = false};
+ EXPECT_TRUE(setActiveConfigWithConstraints(display, config2, constraints, &timeline)
+ .isOk());
+
+ EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
+ // Refresh rate should change within a reasonable time
+ constexpr std::chrono::nanoseconds kReasonableTimeForChange = 1s; // 1 second
+ EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
+ kReasonableTimeForChange.count());
+
+ if (timeline.refreshRequired) {
+ if (params.refreshMiss) {
+ // Miss the refresh frame on purpose to make sure the implementation sends a
+ // callback
+ std::this_thread::sleep_until(toTimePoint(timeline.refreshTimeNanos) +
+ 100ms);
+ }
+ sendRefreshFrame(display, &timeline);
+ }
+ waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos,
+ vsyncPeriod1, vsyncPeriod2);
+
+ // At this point the refresh rate should have changed already, however in rare
+ // cases the implementation might have missed the deadline. In this case a new
+ // timeline should have been provided.
+ auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
+ if (timeline.refreshRequired && params.refreshMiss) {
+ EXPECT_TRUE(newTimeline.has_value());
+ }
+
+ if (newTimeline.has_value()) {
+ if (newTimeline->refreshRequired) {
+ sendRefreshFrame(display, &newTimeline.value());
+ }
+ waitForVsyncPeriodChange(display.get(), newTimeline.value(),
+ constraints.desiredTimeNanos, vsyncPeriod1,
+ vsyncPeriod2);
+ }
+
+ int32_t vsyncPeriodNanos;
+ EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
+ .isOk());
+ EXPECT_EQ(vsyncPeriodNanos, vsyncPeriod2);
+ });
+ }
+ }
+
+ // clang-format off
+ const std::array<float, 16> kIdentity = {{
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ }};
+ // clang-format on
+
+ std::unique_ptr<CommandWriterBase> mWriter;
+ std::unique_ptr<TestCommandReader> mReader;
+};
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_COLOR_TRANSFORM) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->setColorTransform(kIdentity.data(), ColorTransform::IDENTITY);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SetLayerColorTransform) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerColorTransform(kIdentity.data());
+ execute();
+
+ if (mReader->mErrors.size() == 1 && mReader->mErrors[0].second == EX_UNSUPPORTED_OPERATION) {
+ mReader->mErrors.clear();
+ GTEST_SUCCEED() << "setLayerColorTransform is not supported";
+ return;
+ }
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_CLIENT_TARGET) {
+ EXPECT_TRUE(
+ mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN, std::vector<Rect>());
+
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_OUTPUT_BUFFER) {
+ int32_t virtualDisplayCount;
+ EXPECT_TRUE(mComposerClient->getMaxVirtualDisplayCount(&virtualDisplayCount).isOk());
+ if (virtualDisplayCount == 0) {
+ GTEST_SUCCEED() << "no virtual display support";
+ return;
+ }
+
+ VirtualDisplay display;
+ EXPECT_TRUE(mComposerClient
+ ->createVirtualDisplay(64, 64, common::PixelFormat::IMPLEMENTATION_DEFINED,
+ kBufferSlotCount, &display)
+ .isOk());
+
+ mWriter->selectDisplay(display.display);
+ auto handle = allocate()->handle;
+ mWriter->setOutputBuffer(0, handle, -1);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, VALIDATE_DISPLAY) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->validateDisplay();
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, ACCEPT_DISPLAY_CHANGES) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->validateDisplay();
+ mWriter->acceptDisplayChanges();
+ execute();
+}
+
+// TODO(b/208441745) fix the test failure
+TEST_P(GraphicsComposerAidlCommandTest, PRESENT_DISPLAY) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->validateDisplay();
+ mWriter->presentDisplay();
+ execute();
+}
+
+/**
+ * Test IComposerClient::Command::PRESENT_DISPLAY
+ *
+ * Test that IComposerClient::Command::PRESENT_DISPLAY works without
+ * additional call to validateDisplay when only the layer buffer handle and
+ * surface damage have been set
+ */
+// TODO(b/208441745) fix the test failure
+TEST_P(GraphicsComposerAidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) {
+ std::vector<Capability> capabilities;
+ EXPECT_TRUE(mComposer->getCapabilities(&capabilities).isOk());
+ if (none_of(capabilities.begin(), capabilities.end(),
+ [&](auto item) { return item == Capability::SKIP_VALIDATE; })) {
+ GTEST_SUCCEED() << "Device does not have skip validate capability, skipping";
+ return;
+ }
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON);
+
+ std::vector<RenderIntent> renderIntents;
+ mComposerClient->getRenderIntents(mPrimaryDisplay, ColorMode::NATIVE, &renderIntents);
+ for (auto intent : renderIntents) {
+ mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE, intent);
+
+ auto handle = allocate()->handle;
+ ASSERT_NE(nullptr, handle);
+
+ Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+ mWriter->selectLayer(layer);
+ mWriter->setLayerCompositionType(Composition::DEVICE);
+ mWriter->setLayerDisplayFrame(displayFrame);
+ mWriter->setLayerPlaneAlpha(1);
+ mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight});
+ mWriter->setLayerTransform(static_cast<Transform>(0));
+ mWriter->setLayerVisibleRegion(std::vector<Rect>(1, displayFrame));
+ mWriter->setLayerZOrder(10);
+ mWriter->setLayerBlendMode(BlendMode::NONE);
+ mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, displayFrame));
+ mWriter->setLayerBuffer(0, handle, -1);
+ mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ GTEST_SUCCEED() << "Composition change requested, skipping test";
+ return;
+ }
+
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->selectLayer(layer);
+ auto handle2 = allocate()->handle;
+ ASSERT_NE(nullptr, handle2);
+ mWriter->setLayerBuffer(0, handle2, -1);
+ mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, {0, 0, 10, 10}));
+ mWriter->presentDisplay();
+ execute();
+ }
+}
+
+// TODO(b/208441745) fix the test failure
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_CURSOR_POSITION) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ auto handle = allocate()->handle;
+ ASSERT_NE(nullptr, handle);
+ Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBuffer(0, handle, -1);
+ mWriter->setLayerCompositionType(Composition::CURSOR);
+ mWriter->setLayerDisplayFrame(displayFrame);
+ mWriter->setLayerPlaneAlpha(1);
+ mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight});
+ mWriter->setLayerTransform(static_cast<Transform>(0));
+ mWriter->setLayerVisibleRegion(std::vector<Rect>(1, displayFrame));
+ mWriter->setLayerZOrder(10);
+ mWriter->setLayerBlendMode(BlendMode::NONE);
+ mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, displayFrame));
+ mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+ mWriter->validateDisplay();
+
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ GTEST_SUCCEED() << "Composition change requested, skipping test";
+ return;
+ }
+ mWriter->presentDisplay();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->setLayerCursorPosition(1, 1);
+ mWriter->setLayerCursorPosition(0, 0);
+ mWriter->validateDisplay();
+ mWriter->presentDisplay();
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_BUFFER) {
+ auto handle = allocate()->handle;
+ ASSERT_NE(nullptr, handle);
+
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBuffer(0, handle, -1);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ Rect empty{0, 0, 0, 0};
+ Rect unit{0, 0, 1, 1};
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, empty));
+ mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, unit));
+ mWriter->setLayerSurfaceDamage(std::vector<Rect>());
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_BLEND_MODE) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBlendMode(BlendMode::NONE);
+ mWriter->setLayerBlendMode(BlendMode::PREMULTIPLIED);
+ mWriter->setLayerBlendMode(BlendMode::COVERAGE);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_COLOR) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerColor(Color{static_cast<int8_t>(0xff), static_cast<int8_t>(0xff),
+ static_cast<int8_t>(0xff), static_cast<int8_t>(0xff)});
+ mWriter->setLayerColor(Color{0, 0, 0, 0});
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_COMPOSITION_TYPE) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerCompositionType(Composition::CLIENT);
+ mWriter->setLayerCompositionType(Composition::DEVICE);
+ mWriter->setLayerCompositionType(Composition::SOLID_COLOR);
+ mWriter->setLayerCompositionType(Composition::CURSOR);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_DATASPACE) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_DISPLAY_FRAME) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerDisplayFrame(Rect{0, 0, 1, 1});
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_PLANE_ALPHA) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerPlaneAlpha(0.0f);
+ mWriter->setLayerPlaneAlpha(1.0f);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_SIDEBAND_STREAM) {
+ std::vector<Capability> capabilities;
+ EXPECT_TRUE(mComposer->getCapabilities(&capabilities).isOk());
+ if (none_of(capabilities.begin(), capabilities.end(),
+ [&](auto& item) { return item == Capability::SIDEBAND_STREAM; })) {
+ GTEST_SUCCEED() << "no sideband stream support";
+ return;
+ }
+
+ auto handle = allocate()->handle;
+ ASSERT_NE(nullptr, handle);
+
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerSidebandStream(handle);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_SOURCE_CROP) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerSourceCrop(FRect{0.0f, 0.0f, 1.0f, 1.0f});
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_TRANSFORM) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerTransform(static_cast<Transform>(0));
+ mWriter->setLayerTransform(Transform::FLIP_H);
+ mWriter->setLayerTransform(Transform::FLIP_V);
+ mWriter->setLayerTransform(Transform::ROT_90);
+ mWriter->setLayerTransform(Transform::ROT_180);
+ mWriter->setLayerTransform(Transform::ROT_270);
+ mWriter->setLayerTransform(static_cast<Transform>(static_cast<int>(Transform::FLIP_H) |
+ static_cast<int>(Transform::ROT_90)));
+ mWriter->setLayerTransform(static_cast<Transform>(static_cast<int>(Transform::FLIP_V) |
+ static_cast<int>(Transform::ROT_90)));
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_VISIBLE_REGION) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ Rect empty{0, 0, 0, 0};
+ Rect unit{0, 0, 1, 1};
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerVisibleRegion(std::vector<Rect>(1, empty));
+ mWriter->setLayerVisibleRegion(std::vector<Rect>(1, unit));
+ mWriter->setLayerVisibleRegion(std::vector<Rect>());
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_Z_ORDER) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerZOrder(10);
+ mWriter->setLayerZOrder(0);
+ execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_PER_FRAME_METADATA) {
+ int64_t layer;
+ EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+
+ /**
+ * DISPLAY_P3 is a color space that uses the DCI_P3 primaries,
+ * the D65 white point and the SRGB transfer functions.
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.265 0.690
+ * blue 0.150 0.060
+ * red 0.680 0.320
+ * white (D65) 0.3127 0.3290
+ */
+
+ std::vector<PerFrameMetadata> aidlMetadata;
+ aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, 0.680f});
+ aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, 0.320f});
+ aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X, 0.265f});
+ aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y, 0.690f});
+ aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X, 0.150f});
+ aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y, 0.060f});
+ aidlMetadata.push_back({PerFrameMetadataKey::WHITE_POINT_X, 0.3127f});
+ aidlMetadata.push_back({PerFrameMetadataKey::WHITE_POINT_Y, 0.3290f});
+ aidlMetadata.push_back({PerFrameMetadataKey::MAX_LUMINANCE, 100.0f});
+ aidlMetadata.push_back({PerFrameMetadataKey::MIN_LUMINANCE, 0.1f});
+ aidlMetadata.push_back({PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, 78.0});
+ aidlMetadata.push_back({PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0});
+ mWriter->setLayerPerFrameMetadata(aidlMetadata);
+ execute();
+
+ if (mReader->mErrors.size() == 1 && mReader->mErrors[0].second == EX_UNSUPPORTED_OPERATION) {
+ mReader->mErrors.clear();
+ GTEST_SUCCEED() << "SetLayerPerFrameMetadata is not supported";
+ EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
+ return;
+ }
+
+ EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, setActiveConfigWithConstraints) {
+ Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, setActiveConfigWithConstraints_Delayed) {
+ Test_setActiveConfigWithConstraints({.delayForChange = 300'000'000, // 300ms
+ .refreshMiss = false});
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, setActiveConfigWithConstraints_MissRefresh) {
+ Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = true});
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, getDisplayVsyncPeriod) {
+ for (VtsDisplay& display : mDisplays) {
+ std::vector<int32_t> configs;
+ EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
+ for (int32_t config : configs) {
+ int32_t expectedVsyncPeriodNanos = -1;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config,
+ DisplayAttribute::VSYNC_PERIOD,
+ &expectedVsyncPeriodNanos)
+ .isOk());
+
+ VsyncPeriodChangeTimeline timeline;
+ VsyncPeriodChangeConstraints constraints;
+
+ constraints.desiredTimeNanos = systemTime();
+ constraints.seamlessRequired = false;
+ EXPECT_TRUE(mComposerClient
+ ->setActiveConfigWithConstraints(display.get(), config, constraints,
+ &timeline)
+ .isOk());
+
+ if (timeline.refreshRequired) {
+ sendRefreshFrame(display, &timeline);
+ }
+ waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos, 0,
+ expectedVsyncPeriodNanos);
+
+ int32_t vsyncPeriodNanos;
+ int retryCount = 100;
+ do {
+ std::this_thread::sleep_for(10ms);
+ vsyncPeriodNanos = 0;
+ EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
+ .isOk());
+ --retryCount;
+ } while (vsyncPeriodNanos != expectedVsyncPeriodNanos && retryCount > 0);
+
+ EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
+
+ // Make sure that the vsync period stays the same if the active config is not
+ // changed.
+ auto timeout = 1ms;
+ for (int i = 0; i < 10; i++) {
+ std::this_thread::sleep_for(timeout);
+ timeout *= 2;
+ vsyncPeriodNanos = 0;
+ EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
+ .isOk());
+ EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
+ }
+ }
+ }
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
+ VsyncPeriodChangeTimeline timeline;
+ VsyncPeriodChangeConstraints constraints;
+
+ constraints.seamlessRequired = true;
+ constraints.desiredTimeNanos = systemTime();
+
+ for (VtsDisplay& display : mDisplays) {
+ forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) {
+ int32_t configGroup1;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config1,
+ DisplayAttribute::CONFIG_GROUP, &configGroup1)
+ .isOk());
+ int32_t configGroup2;
+ EXPECT_TRUE(mComposerClient
+ ->getDisplayAttribute(display.get(), config2,
+ DisplayAttribute::CONFIG_GROUP, &configGroup2)
+ .isOk());
+ if (configGroup1 != configGroup2) {
+ setActiveConfig(display, config1);
+ sendRefreshFrame(display, nullptr);
+ EXPECT_EQ(IComposerClient::EX_SEAMLESS_NOT_ALLOWED,
+ setActiveConfigWithConstraints(display, config2, constraints, &timeline)
+ .getServiceSpecificError());
+ }
+ });
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, GraphicsComposerAidlCommandTest,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+ ::android::PrintInstanceNameToString);
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, GraphicsComposerAidlTest,
diff --git a/health/aidl/README.md b/health/aidl/README.md
index 0d7c4c9..a64fe93 100644
--- a/health/aidl/README.md
+++ b/health/aidl/README.md
@@ -63,8 +63,7 @@
* You may ignore the `service` line. The name of the service does not matter.
* If your service belongs to additional classes beside `charger`, you need a
custom health AIDL service.
-* You may ignore the `seclabel` line. When the health AIDL service runs in
- charger mode, its original SELinux domain is kept.
+* Modify the `seclabel` line. Replace `charger` with `charger_vendor`.
* If your service has a different `user` (not `system`), you need a custom
health AIDL service.
* If your service belongs to additional `group`s beside
@@ -240,6 +239,8 @@
```text
service vendor.charger-tuna /vendor/bin/hw/android.hardware.health-service-tuna --charger
+ class charger
+ seclabel u:r:charger_vendor:s0
# ...
```
@@ -315,6 +316,5 @@
`hal_health_tuna`:
```text
-type hal_health_tuna, charger_type, domain;
-hal_server_domain(hal_health_default, hal_health)
+domain_trans(init, hal_health_tuna_exec, charger_vendor)
```
diff --git a/health/aidl/default/android.hardware.health-service.example.rc b/health/aidl/default/android.hardware.health-service.example.rc
index dee3d11..4258890 100644
--- a/health/aidl/default/android.hardware.health-service.example.rc
+++ b/health/aidl/default/android.hardware.health-service.example.rc
@@ -7,6 +7,7 @@
service vendor.charger-default /vendor/bin/hw/android.hardware.health-service.example --charger
class charger
+ seclabel u:r:charger_vendor:s0
user system
group system wakelock input
capabilities SYS_BOOT
diff --git a/health/storage/aidl/default/main.cpp b/health/storage/aidl/default/main.cpp
index 186b64c..74e266f 100644
--- a/health/storage/aidl/default/main.cpp
+++ b/health/storage/aidl/default/main.cpp
@@ -24,14 +24,19 @@
using std::string_literals::operator""s;
int main() {
+ LOG(INFO) << "Health storage AIDL HAL starting...";
ABinderProcess_setThreadPoolMaxThreadCount(0);
// make a default storage service
auto storage = ndk::SharedRefBase::make<Storage>();
const std::string name = Storage::descriptor + "/default"s;
+ LOG(INFO) << "Health storage AIDL HAL registering...";
CHECK_EQ(STATUS_OK,
AServiceManager_registerLazyService(storage->asBinder().get(), name.c_str()));
+ LOG(INFO) << "Health storage AIDL HAL joining...";
ABinderProcess_joinThreadPool();
+
+ LOG(ERROR) << "Health storage AIDL HAL join thread ends, exiting...";
return EXIT_FAILURE; // should not reach
}
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 2c15823..7676147 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -81,6 +81,12 @@
namespace test {
namespace {
+// The maximum number of times we'll attempt to verify that corruption
+// of an encrypted blob results in an error. Retries are necessary as there
+// is a small (roughly 1/256) chance that corrupting ciphertext still results
+// in valid PKCS7 padding.
+constexpr size_t kMaxPaddingCorruptionRetries = 8;
+
template <TagType tag_type, Tag tag, typename ValueT>
bool contains(hidl_vec<KeyParameter>& set, TypedTag<tag_type, tag> ttag, ValueT expected_value) {
size_t count = std::count_if(set.begin(), set.end(), [&](const KeyParameter& param) {
@@ -2853,11 +2859,22 @@
string ciphertext = EncryptMessage(message, params);
EXPECT_EQ(16U, ciphertext.size());
EXPECT_NE(ciphertext, message);
- ++ciphertext[ciphertext.size() / 2];
- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
- string plaintext;
- EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &plaintext));
+ for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+ ++ciphertext[ciphertext.size() / 2];
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+ string plaintext;
+ ErrorCode error = Finish(message, &plaintext);
+ if (error == ErrorCode::INVALID_INPUT_LENGTH) {
+ // This is the expected error, we can exit the test now.
+ return;
+ } else {
+ // Very small chance we got valid decryption, so try again.
+ ASSERT_EQ(error, ErrorCode::OK);
+ }
+ }
+ FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
}
HidlBuf CopyIv(const AuthorizationSet& set) {
@@ -3923,17 +3940,30 @@
string ciphertext = EncryptMessage(message, BlockMode::ECB, PaddingMode::PKCS7);
EXPECT_EQ(8U, ciphertext.size());
EXPECT_NE(ciphertext, message);
- ++ciphertext[ciphertext.size() / 2];
AuthorizationSetBuilder begin_params;
begin_params.push_back(TAG_BLOCK_MODE, BlockMode::ECB);
begin_params.push_back(TAG_PADDING, PaddingMode::PKCS7);
- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
- string plaintext;
- size_t input_consumed;
- EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+
+ for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+ ++ciphertext[ciphertext.size() / 2];
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+ string plaintext;
+
+ size_t input_consumed;
+ EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
+ EXPECT_EQ(ciphertext.size(), input_consumed);
+ ErrorCode error = Finish(&plaintext);
+ if (error == ErrorCode::INVALID_ARGUMENT) {
+ // This is the expected error, we can exit the test now.
+ return;
+ } else {
+ // Very small chance we got valid decryption, so try again.
+ ASSERT_EQ(error, ErrorCode::OK);
+ }
+ }
+ FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
}
struct TripleDesTestVector {
@@ -4234,18 +4264,28 @@
string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
EXPECT_EQ(8U, ciphertext.size());
EXPECT_NE(ciphertext, message);
- ++ciphertext[ciphertext.size() / 2];
auto begin_params = AuthorizationSetBuilder()
.BlockMode(BlockMode::CBC)
.Padding(PaddingMode::PKCS7)
.Authorization(TAG_NONCE, iv);
- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
- string plaintext;
- size_t input_consumed;
- EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+ for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+ ++ciphertext[ciphertext.size() / 2];
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+ string plaintext;
+ size_t input_consumed;
+ EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
+ EXPECT_EQ(ciphertext.size(), input_consumed);
+ ErrorCode error = Finish(&plaintext);
+ if (error == ErrorCode::INVALID_ARGUMENT) {
+ // This is the expected error, we can exit the test now.
+ return;
+ } else {
+ // Very small chance we got valid decryption, so try again.
+ ASSERT_EQ(error, ErrorCode::OK);
+ }
+ }
+ FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
}
/*
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
index cfcd42c..9df687c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
@@ -52,6 +52,7 @@
int mtuV6;
boolean preferred;
boolean persistent;
+ boolean alwaysOn;
const int ID_DEFAULT = 0;
const int ID_TETHERED = 1;
const int ID_IMS = 2;
diff --git a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
index 7657fc9..a14963f 100644
--- a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
@@ -115,4 +115,11 @@
* If the same data profile exists, this data profile must overwrite it.
*/
boolean persistent;
+ /**
+ * Indicates the PDU session brought up by this data profile should be always-on.
+ * An always-on PDU Session is a PDU Session for which User Plane resources have to be
+ * activated during every transition from CM-IDLE mode to CM-CONNECTED state.
+ * See 3GPP TS 23.501 section 5.6.13 for the details.
+ */
+ boolean alwaysOn;
}
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index 028d297..3cf6ff2 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -38,3 +38,30 @@
},
versions: ["1"],
}
+
+// cc_defaults that includes the latest KeyMint AIDL library.
+// Modules that depend on KeyMint directly can include this cc_defaults to avoid
+// managing dependency versions explicitly.
+cc_defaults {
+ name: "keymint_use_latest_hal_aidl_ndk_static",
+ static_libs: [
+ "android.hardware.security.keymint-V1-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "keymint_use_latest_hal_aidl_ndk_shared",
+ shared_libs: [
+ "android.hardware.security.keymint-V1-ndk",
+ ],
+}
+
+// A rust_defaults that includes the latest KeyMint AIDL library.
+// Modules that depend on KeyMint directly can include this cc_defaults to avoid
+// managing dependency versions explicitly.
+rust_defaults {
+ name: "keymint_use_latest_hal_aidl_rust",
+ rustlibs: [
+ "android.hardware.security.keymint-V1-rust",
+ ],
+}
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index c2918ef..1a17fd4 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -21,8 +21,10 @@
"-Wall",
"-Wextra",
],
+ defaults: [
+ "keymint_use_latest_hal_aidl_ndk_shared",
+ ],
shared_libs: [
- "android.hardware.security.keymint-V1-ndk",
"android.hardware.security.sharedsecret-V1-ndk",
"android.hardware.security.secureclock-V1-ndk",
"libbase",
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index ff6a6f8..2d2d701 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_defaults {
name: "keymint_vts_defaults",
defaults: [
+ "keymint_use_latest_hal_aidl_ndk_static",
"use_libaidlvintf_gtest_helper_static",
"VtsHalTargetTestDefaults",
],
@@ -34,7 +35,6 @@
"libcrypto",
],
static_libs: [
- "android.hardware.security.keymint-V1-ndk",
"android.hardware.security.secureclock-V1-ndk",
"libcppbor_external",
"libcppcose_rkp",
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 12ce859..6140df1 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -1067,6 +1067,8 @@
}
} else {
switch (algorithm) {
+ case Algorithm::AES:
+ return {64, 96, 131, 512};
case Algorithm::TRIPLE_DES:
return {56};
default:
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 919d79f..c99e1d0 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -69,8 +69,11 @@
namespace {
+// Whether to check that BOOT_PATCHLEVEL is populated.
+bool check_boot_pl = true;
+
// The maximum number of times we'll attempt to verify that corruption
-// of an ecrypted blob results in an error. Retries are necessary as there
+// of an encrypted blob results in an error. Retries are necessary as there
// is a small (roughly 1/256) chance that corrupting ciphertext still results
// in valid PKCS7 padding.
constexpr size_t kMaxPaddingCorruptionRetries = 8;
@@ -527,12 +530,17 @@
EXPECT_TRUE(os_pl);
EXPECT_EQ(*os_pl, os_patch_level());
- // Should include vendor and boot patchlevels.
+ // Should include vendor patchlevel.
auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
EXPECT_TRUE(vendor_pl);
EXPECT_EQ(*vendor_pl, vendor_patch_level());
- auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
- EXPECT_TRUE(boot_pl);
+
+ // Should include boot patchlevel (but there are some test scenarios where this is not
+ // possible).
+ if (check_boot_pl) {
+ auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+ EXPECT_TRUE(boot_pl);
+ }
return auths;
}
@@ -6914,6 +6922,12 @@
} else {
std::cout << "NOT dumping attestations" << std::endl;
}
+ if (std::string(argv[i]) == "--skip_boot_pl_check") {
+ // Allow checks of BOOT_PATCHLEVEL to be disabled, so that the tests can
+ // be run in emulated environments that don't have the normal bootloader
+ // interactions.
+ aidl::android::hardware::security::keymint::test::check_boot_pl = false;
+ }
}
}
return RUN_ALL_TESTS();
diff --git a/security/keymint/aidl/vts/performance/Android.bp b/security/keymint/aidl/vts/performance/Android.bp
index 355f87b..7e3a3e5 100644
--- a/security/keymint/aidl/vts/performance/Android.bp
+++ b/security/keymint/aidl/vts/performance/Android.bp
@@ -27,6 +27,7 @@
name: "VtsAidlKeyMintBenchmarkTest",
defaults: [
"VtsHalTargetTestDefaults",
+ "keymint_use_latest_hal_aidl_ndk_static",
"use_libaidlvintf_gtest_helper_static",
],
srcs: [
@@ -39,7 +40,6 @@
"libkeymint_support",
],
static_libs: [
- "android.hardware.security.keymint-V1-ndk",
"android.hardware.security.secureclock-V1-ndk",
"libcppbor_external",
"libchrome",
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index e162934..36969bb 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -40,8 +40,10 @@
export_include_dirs: [
"include",
],
+ defaults: [
+ "keymint_use_latest_hal_aidl_ndk_shared",
+ ],
shared_libs: [
- "android.hardware.security.keymint-V1-ndk",
"libbase",
"libcrypto",
"libutils",
diff --git a/security/secureclock/aidl/vts/functional/Android.bp b/security/secureclock/aidl/vts/functional/Android.bp
index 806517d..a34668b 100644
--- a/security/secureclock/aidl/vts/functional/Android.bp
+++ b/security/secureclock/aidl/vts/functional/Android.bp
@@ -27,6 +27,7 @@
name: "VtsAidlSecureClockTargetTest",
defaults: [
"VtsHalTargetTestDefaults",
+ "keymint_use_latest_hal_aidl_ndk_static",
"use_libaidlvintf_gtest_helper_static",
],
cflags: [
@@ -41,7 +42,6 @@
"libcrypto",
],
static_libs: [
- "android.hardware.security.keymint-V1-ndk",
"android.hardware.security.secureclock-V1-ndk",
"libkeymint",
],
diff --git a/security/sharedsecret/aidl/vts/functional/Android.bp b/security/sharedsecret/aidl/vts/functional/Android.bp
index 94da675..1f0f6a6 100644
--- a/security/sharedsecret/aidl/vts/functional/Android.bp
+++ b/security/sharedsecret/aidl/vts/functional/Android.bp
@@ -27,6 +27,7 @@
name: "VtsAidlSharedSecretTargetTest",
defaults: [
"VtsHalTargetTestDefaults",
+ "keymint_use_latest_hal_aidl_ndk_static",
"use_libaidlvintf_gtest_helper_static",
],
srcs: [
@@ -41,7 +42,6 @@
"libcrypto",
],
static_libs: [
- "android.hardware.security.keymint-V1-ndk",
"android.hardware.security.sharedsecret-V1-ndk",
"libkeymint",
],
diff --git a/tv/tuner/aidl/default/Filter.cpp b/tv/tuner/aidl/default/Filter.cpp
index 5f61c8d..54037be 100644
--- a/tv/tuner/aidl/default/Filter.cpp
+++ b/tv/tuner/aidl/default/Filter.cpp
@@ -35,7 +35,11 @@
#define WAIT_TIMEOUT 3000000000
FilterCallbackScheduler::FilterCallbackScheduler(const std::shared_ptr<IFilterCallback>& cb)
- : mCallback(cb), mDataLength(0), mTimeDelayInMs(0), mDataSizeDelayInBytes(0) {
+ : mCallback(cb),
+ mIsConditionMet(false),
+ mDataLength(0),
+ mTimeDelayInMs(0),
+ mDataSizeDelayInBytes(0) {
start();
}
@@ -44,12 +48,14 @@
}
void FilterCallbackScheduler::onFilterEvent(DemuxFilterEvent&& event) {
- std::lock_guard<std::mutex> lock(mLock);
+ std::unique_lock<std::mutex> lock(mLock);
mCallbackBuffer.push_back(std::move(event));
mDataLength += getDemuxFilterEventDataLength(event);
- if (mDataLength >= mDataSizeDelayInBytes) {
- // size limit has been reached, send out events
+ if (isDataSizeDelayConditionMetLocked()) {
+ mIsConditionMet = true;
+ // unlock, so thread is not immediately blocked when it is notified.
+ lock.unlock();
mCv.notify_all();
}
}
@@ -67,21 +73,22 @@
}
void FilterCallbackScheduler::setTimeDelayHint(int timeDelay) {
- // updating the setTimeDelay does not go into effect until the condition
- // variable times out or is notified.
- // One possibility is to notify the condition variable right away when the
- // time delay changes, but I don't see the benefit over waiting for the next
- // timeout / push, since -- in any case -- this will not change very often.
+ std::unique_lock<std::mutex> lock(mLock);
mTimeDelayInMs = timeDelay;
+ // always notify condition variable to update timeout
+ mIsConditionMet = true;
+ lock.unlock();
+ mCv.notify_all();
}
void FilterCallbackScheduler::setDataSizeDelayHint(int dataSizeDelay) {
- // similar to updating the time delay hint, when mDataSizeDelayInBytes
- // changes, this will not go into immediate effect, but will wait until the
- // next filterEvent.
- // We could technically check the current data length and notify the
- // condition variable if we wanted to, but again, this may be overkill.
+ std::unique_lock<std::mutex> lock(mLock);
mDataSizeDelayInBytes = dataSizeDelay;
+ if (isDataSizeDelayConditionMetLocked()) {
+ mIsConditionMet = true;
+ lock.unlock();
+ mCv.notify_all();
+ }
}
bool FilterCallbackScheduler::hasCallbackRegistered() const {
@@ -96,6 +103,10 @@
void FilterCallbackScheduler::stop() {
mIsRunning = false;
if (mCallbackThread.joinable()) {
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ mIsConditionMet = true;
+ }
mCv.notify_all();
mCallbackThread.join();
}
@@ -109,17 +120,15 @@
void FilterCallbackScheduler::threadLoopOnce() {
std::unique_lock<std::mutex> lock(mLock);
- // mTimeDelayInMs is an atomic value, so it should be copied into a local
- // variable before use (to make sure both the if statement and wait_for use
- // the same value).
- int timeDelayInMs = mTimeDelayInMs;
- if (timeDelayInMs > 0) {
- mCv.wait_for(lock, std::chrono::milliseconds(timeDelayInMs));
+ if (mTimeDelayInMs > 0) {
+ // Note: predicate protects from lost and spurious wakeups
+ mCv.wait_for(lock, std::chrono::milliseconds(mTimeDelayInMs),
+ [this] { return mIsConditionMet; });
} else {
- // no reason to timeout, just wait until main thread determines it's
- // okay to send data.
- mCv.wait(lock);
+ // Note: predicate protects from lost and spurious wakeups
+ mCv.wait(lock, [this] { return mIsConditionMet; });
}
+ mIsConditionMet = false;
// condition_variable wait locks mutex on timeout / notify
// Note: if stop() has been called in the meantime, do not send more filter
@@ -131,7 +140,22 @@
mCallbackBuffer.clear();
mDataLength = 0;
}
- lock.unlock();
+}
+
+// mLock needs to be held to call this function
+bool FilterCallbackScheduler::isDataSizeDelayConditionMetLocked() {
+ if (mDataSizeDelayInBytes == 0) {
+ // Data size delay is disabled.
+ if (mTimeDelayInMs == 0) {
+ // Events should only be sent immediately if time delay is disabled
+ // as well.
+ return true;
+ }
+ return false;
+ }
+
+ // Data size delay is enabled.
+ return mDataLength >= mDataSizeDelayInBytes;
}
int FilterCallbackScheduler::getDemuxFilterEventDataLength(const DemuxFilterEvent& event) {
@@ -542,7 +566,9 @@
// For the first time of filter output, implementation needs to send the filter
// Event Callback without waiting for the DATA_CONSUMED to init the process.
while (mFilterThreadRunning) {
+ std::unique_lock<std::mutex> lock(mFilterEventsLock);
if (mFilterEvents.size() == 0) {
+ lock.unlock();
if (DEBUG_FILTER) {
ALOGD("[Filter] wait for filter data output.");
}
@@ -559,6 +585,7 @@
mConfigured = false;
}
+ // lock is still being held
for (auto&& event : mFilterEvents) {
mCallbackScheduler.onFilterEvent(std::move(event));
}
@@ -741,7 +768,6 @@
}
::ndk::ScopedAStatus Filter::startPesFilterHandler() {
- std::lock_guard<std::mutex> lock(mFilterEventsLock);
if (mFilterOutput.empty()) {
return ::ndk::ScopedAStatus::ok();
}
@@ -796,7 +822,11 @@
ALOGD("[Filter] assembled pes data length %d", pesEvent.dataLength);
}
- mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::pes>(pesEvent));
+ {
+ std::lock_guard<std::mutex> lock(mFilterEventsLock);
+ mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::pes>(pesEvent));
+ }
+
mPesOutput.clear();
}
@@ -811,7 +841,6 @@
}
::ndk::ScopedAStatus Filter::startMediaFilterHandler() {
- std::lock_guard<std::mutex> lock(mFilterEventsLock);
if (mFilterOutput.empty()) {
return ::ndk::ScopedAStatus::ok();
}
@@ -900,7 +929,12 @@
.firstMbInSlice = 0, // random address
};
- mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::tsRecord>(recordEvent));
+ {
+ std::lock_guard<std::mutex> lock(mFilterEventsLock);
+ mFilterEvents.push_back(
+ DemuxFilterEvent::make<DemuxFilterEvent::Tag::tsRecord>(recordEvent));
+ }
+
mRecordFilterOutput.clear();
return ::ndk::ScopedAStatus::ok();
}
@@ -918,7 +952,6 @@
bool Filter::writeSectionsAndCreateEvent(vector<int8_t>& data) {
// TODO check how many sections has been read
ALOGD("[Filter] section handler");
- std::lock_guard<std::mutex> lock(mFilterEventsLock);
if (!writeDataToFilterMQ(data)) {
return false;
}
@@ -930,7 +963,12 @@
.sectionNum = 1,
.dataLength = static_cast<int32_t>(data.size()),
};
- mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::section>(secEvent));
+
+ {
+ std::lock_guard<std::mutex> lock(mFilterEventsLock);
+ mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::section>(secEvent));
+ }
+
return true;
}
@@ -1028,7 +1066,11 @@
mediaEvent.pts = mPts;
mPts = 0;
}
- mFilterEvents.push_back(std::move(event));
+
+ {
+ std::lock_guard<std::mutex> lock(mFilterEventsLock);
+ mFilterEvents.push_back(std::move(event));
+ }
// Clear and log
native_handle_close(nativeHandle);
@@ -1068,7 +1110,11 @@
mediaEvent.pts = mPts;
mPts = 0;
}
- mFilterEvents.push_back(std::move(event));
+
+ {
+ std::lock_guard<std::mutex> lock(mFilterEventsLock);
+ mFilterEvents.push_back(std::move(event));
+ }
mSharedAvMemOffset += output.size();
@@ -1092,8 +1138,6 @@
void Filter::createMediaEvent(vector<DemuxFilterEvent>& events) {
AudioExtraMetaData audio;
- events.resize(1);
-
audio.adFade = 1;
audio.adPan = 2;
audio.versionTextTag = 3;
@@ -1101,17 +1145,15 @@
audio.adGainFront = 5;
audio.adGainSurround = 6;
- events[0] = DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>();
- events[0].get<DemuxFilterEvent::Tag::media>().streamId = 1;
- events[0].get<DemuxFilterEvent::Tag::media>().isPtsPresent = true;
- events[0].get<DemuxFilterEvent::Tag::media>().dataLength = 3;
- events[0].get<DemuxFilterEvent::Tag::media>().offset = 4;
- events[0].get<DemuxFilterEvent::Tag::media>().isSecureMemory = true;
- events[0].get<DemuxFilterEvent::Tag::media>().mpuSequenceNumber = 6;
- events[0].get<DemuxFilterEvent::Tag::media>().isPesPrivateData = true;
- events[0]
- .get<DemuxFilterEvent::Tag::media>()
- .extraMetaData.set<DemuxFilterMediaEventExtraMetaData::Tag::audio>(audio);
+ DemuxFilterMediaEvent mediaEvent;
+ mediaEvent.streamId = 1;
+ mediaEvent.isPtsPresent = true;
+ mediaEvent.dataLength = 3;
+ mediaEvent.offset = 4;
+ mediaEvent.isSecureMemory = true;
+ mediaEvent.mpuSequenceNumber = 6;
+ mediaEvent.isPesPrivateData = true;
+ mediaEvent.extraMetaData.set<DemuxFilterMediaEventExtraMetaData::Tag::audio>(audio);
int av_fd = createAvIonFd(BUFFER_SIZE_16M);
if (av_fd == -1) {
@@ -1129,16 +1171,16 @@
uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
mDataId2Avfd[dataId] = dup(av_fd);
- events[0].get<DemuxFilterEvent::Tag::media>().avDataId = static_cast<int64_t>(dataId);
- events[0].get<DemuxFilterEvent::Tag::media>().avMemory = ::android::dupToAidl(nativeHandle);
+ mediaEvent.avDataId = static_cast<int64_t>(dataId);
+ mediaEvent.avMemory = ::android::dupToAidl(nativeHandle);
+
+ events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>(std::move(mediaEvent)));
native_handle_close(nativeHandle);
native_handle_delete(nativeHandle);
}
void Filter::createTsRecordEvent(vector<DemuxFilterEvent>& events) {
- events.resize(2);
-
DemuxPid pid;
DemuxFilterScIndexMask mask;
DemuxFilterTsRecordEvent tsRecord1;
@@ -1153,13 +1195,11 @@
tsRecord2.pts = 1;
tsRecord2.firstMbInSlice = 2; // random address
- events[0].set<DemuxFilterEvent::Tag::tsRecord>(tsRecord1);
- events[1].set<DemuxFilterEvent::Tag::tsRecord>(tsRecord2);
+ events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::tsRecord>(std::move(tsRecord1)));
+ events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::tsRecord>(std::move(tsRecord2)));
}
void Filter::createMmtpRecordEvent(vector<DemuxFilterEvent>& events) {
- events.resize(2);
-
DemuxFilterMmtpRecordEvent mmtpRecord1;
mmtpRecord1.scHevcIndexMask = 1;
mmtpRecord1.byteNumber = 2;
@@ -1170,36 +1210,32 @@
mmtpRecord2.firstMbInSlice = 3;
mmtpRecord2.tsIndexMask = 4;
- events[0].set<DemuxFilterEvent::Tag::mmtpRecord>(mmtpRecord1);
- events[1].set<DemuxFilterEvent::Tag::mmtpRecord>(mmtpRecord2);
+ events.push_back(
+ DemuxFilterEvent::make<DemuxFilterEvent::Tag::mmtpRecord>(std::move(mmtpRecord1)));
+ events.push_back(
+ DemuxFilterEvent::make<DemuxFilterEvent::Tag::mmtpRecord>(std::move(mmtpRecord2)));
}
void Filter::createSectionEvent(vector<DemuxFilterEvent>& events) {
- events.resize(1);
-
DemuxFilterSectionEvent section;
section.tableId = 1;
section.version = 2;
section.sectionNum = 3;
section.dataLength = 0;
- events[0].set<DemuxFilterEvent::Tag::section>(section);
+ events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::section>(std::move(section)));
}
void Filter::createPesEvent(vector<DemuxFilterEvent>& events) {
- events.resize(1);
-
DemuxFilterPesEvent pes;
pes.streamId = 1;
pes.dataLength = 1;
pes.mpuSequenceNumber = 2;
- events[0].set<DemuxFilterEvent::Tag::pes>(pes);
+ events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::pes>(std::move(pes)));
}
void Filter::createDownloadEvent(vector<DemuxFilterEvent>& events) {
- events.resize(1);
-
DemuxFilterDownloadEvent download;
download.itemId = 1;
download.mpuSequenceNumber = 2;
@@ -1207,41 +1243,36 @@
download.lastItemFragmentIndex = 4;
download.dataLength = 0;
- events[0].set<DemuxFilterEvent::Tag::download>(download);
+ events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::download>(std::move(download)));
}
void Filter::createIpPayloadEvent(vector<DemuxFilterEvent>& events) {
- events.resize(1);
-
DemuxFilterIpPayloadEvent ipPayload;
ipPayload.dataLength = 0;
- events[0].set<DemuxFilterEvent::Tag::ipPayload>(ipPayload);
+ events.push_back(
+ DemuxFilterEvent::make<DemuxFilterEvent::Tag::ipPayload>(std::move(ipPayload)));
}
void Filter::createTemiEvent(vector<DemuxFilterEvent>& events) {
- events.resize(1);
-
DemuxFilterTemiEvent temi;
temi.pts = 1;
temi.descrTag = 2;
temi.descrData = {3};
- events[0].set<DemuxFilterEvent::Tag::temi>(temi);
+ events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::temi>(std::move(temi)));
}
void Filter::createMonitorEvent(vector<DemuxFilterEvent>& events) {
- events.resize(1);
-
DemuxFilterMonitorEvent monitor;
monitor.set<DemuxFilterMonitorEvent::Tag::scramblingStatus>(ScramblingStatus::SCRAMBLED);
- events[0].set<DemuxFilterEvent::Tag::monitorEvent>(monitor);
+
+ events.push_back(
+ DemuxFilterEvent::make<DemuxFilterEvent::Tag::monitorEvent>(std::move(monitor)));
}
void Filter::createRestartEvent(vector<DemuxFilterEvent>& events) {
- events.resize(1);
-
- events[0].set<DemuxFilterEvent::Tag::startId>(1);
+ events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::startId>(1));
}
} // namespace tuner
diff --git a/tv/tuner/aidl/default/Filter.h b/tv/tuner/aidl/default/Filter.h
index 7298561..8388c98 100644
--- a/tv/tuner/aidl/default/Filter.h
+++ b/tv/tuner/aidl/default/Filter.h
@@ -77,6 +77,9 @@
void threadLoop();
void threadLoopOnce();
+ // function needs to be called while holding mLock
+ bool isDataSizeDelayConditionMetLocked();
+
static int getDemuxFilterEventDataLength(const DemuxFilterEvent& event);
private:
@@ -84,16 +87,15 @@
std::thread mCallbackThread;
std::atomic<bool> mIsRunning;
- // mLock protects mCallbackBuffer, mCv, and mDataLength
+ // mLock protects mCallbackBuffer, mIsConditionMet, mCv, mDataLength,
+ // mTimeDelayInMs, and mDataSizeDelayInBytes
std::mutex mLock;
std::vector<DemuxFilterEvent> mCallbackBuffer;
+ bool mIsConditionMet;
std::condition_variable mCv;
int mDataLength;
-
- // both of these need to be atomic (not just mTimeDelayInMs) as this class
- // needs to be threadsafe.
- std::atomic<int> mTimeDelayInMs;
- std::atomic<int> mDataSizeDelayInBytes;
+ int mTimeDelayInMs;
+ int mDataSizeDelayInBytes;
};
class Filter : public BnFilter {
diff --git a/wifi/.clang-format b/wifi/.clang-format
deleted file mode 100644
index 25ed932..0000000
--- a/wifi/.clang-format
+++ /dev/null
@@ -1,2 +0,0 @@
-BasedOnStyle: Google
-IndentWidth: 4
\ No newline at end of file