Merge "Update the DOOR_LOCK property to have WRITE access."
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index bf8b547..439c5fb 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -170,8 +170,9 @@
acl_cb_count = 0;
sco_cb_count = 0;
- ASSERT_EQ(initialized, false);
- bluetooth->initialize(bluetooth_cb);
+ ASSERT_FALSE(initialized);
+ // Should not be checked in production code
+ ASSERT_TRUE(bluetooth->initialize(bluetooth_cb).isOk());
bluetooth_cb->SetWaitTimeout(kCallbackNameInitializationComplete,
WAIT_FOR_INIT_TIMEOUT);
@@ -186,15 +187,16 @@
bluetooth_cb->WaitForCallback(kCallbackNameInitializationComplete)
.no_timeout);
- ASSERT_EQ(initialized, true);
+ ASSERT_TRUE(initialized);
}
virtual void TearDown() override {
- bluetooth->close();
- handle_no_ops();
- EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
- EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
- EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
+ // Should not be checked in production code
+ ASSERT_TRUE(bluetooth->close().isOk());
+ handle_no_ops();
+ EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
+ EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
+ EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
}
void setBufferSizes();
diff --git a/current.txt b/current.txt
index 4709ab3..ad45c26 100644
--- a/current.txt
+++ b/current.txt
@@ -390,6 +390,7 @@
684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types
da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
+78886339f2c848cf13c1edd3ebba63f89796b2620d3bf3b5c21d038a53519ba0 android.hardware.gnss@1.0::IGnssMeasurementCallback
b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
1fb32361286b938d48a55c2539c846732afce0b99fe08590f556643125bc13d3 android.hardware.neuralnetworks@1.0::types
diff --git a/gnss/1.0/IGnssMeasurementCallback.hal b/gnss/1.0/IGnssMeasurementCallback.hal
index b27c2e0..d3489e6 100644
--- a/gnss/1.0/IGnssMeasurementCallback.hal
+++ b/gnss/1.0/IGnssMeasurementCallback.hal
@@ -124,6 +124,12 @@
/**
* A set of flags indicating the validity of the fields in this data
* structure.
+ *
+ * Fields for which there is no corresponding flag must be filled in
+ * with a valid value. For convenience, these are marked as mandatory.
+ *
+ * Others fields may have invalid information in them, if not marked as
+ * valid by the corresponding bit in gnssClockFlags.
*/
bitfield<GnssClockFlags> gnssClockFlags;
@@ -155,7 +161,7 @@
* Sub-nanosecond accuracy can be provided by means of the 'biasNs' field.
* The value contains the timeUncertaintyNs in it.
*
- * This field is mandatory.
+ * This value is mandatory.
*/
int64_t timeNs;
@@ -172,29 +178,31 @@
/**
* The difference between hardware clock ('time' field) inside GNSS receiver
- * and the true GNSS time since 0000Z, January 6, 1980, in nanoseconds.
+ * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
*
* The sign of the value is defined by the following equation:
- * local estimate of GNSS time = timeNs - (fullBiasNs + biasNs)
+ * local estimate of GPS time = timeNs - (fullBiasNs + biasNs)
*
- * This value is mandatory if the receiver has estimated GNSS time. If the
- * computed time is for a non-GNSS constellation, the time offset of that
- * constellation to GNSS has to be applied to fill this value. The error
- * estimate for the sum of this and the biasNs is the biasUncertaintyNs,
- * and the caller is responsible for using this uncertainty (it can be very
- * large before the GNSS time has been solved for.) If the data is available
- * gnssClockFlags must contain HAS_FULL_BIAS.
+ * If receiver has computed time for a non-GPS constellation, the time offset of
+ * that constellation versus GPS time must be applied to fill this value.
+ *
+ * The error estimate for the sum of this and the biasNs is the biasUncertaintyNs.
+ *
+ * If the data is available gnssClockFlags must contain HAS_FULL_BIAS.
+ *
+ * This value is mandatory if the receiver has estimated GPS time.
*/
int64_t fullBiasNs;
/**
- * Sub-nanosecond bias.
+ * Sub-nanosecond bias - used with fullBiasNS, see fullBiasNs for details.
+ *
* The error estimate for the sum of this and the fullBiasNs is the
* biasUncertaintyNs.
*
- * If the data is available gnssClockFlags must contain HAS_BIAS. If GNSS
- * has computed a position fix. This value is mandatory if the receiver has
- * estimated GNSS time.
+ * If the data is available gnssClockFlags must contain HAS_BIAS.
+ *
+ * This value is mandatory if the receiver has estimated GPS time.
*/
double biasNs;
@@ -203,9 +211,12 @@
* bias) in nanoseconds. The uncertainty is represented as an absolute
* (single sided) value.
*
- * If the data is available gnssClockFlags must contain
- * HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
- * has estimated GNSS time.
+ * The caller is responsible for using this uncertainty (it can be very
+ * large before the GPS time has been fully resolved.)
+ *
+ * If the data is available gnssClockFlags must contain HAS_BIAS_UNCERTAINTY.
+ *
+ * This value is mandatory if the receiver has estimated GPS time.
*/
double biasUncertaintyNs;
@@ -216,10 +227,9 @@
* frequency, and that the (fullBiasNs + biasNs) is growing more positive
* over time.
*
- * The value contains the 'drift uncertainty' in it.
* If the data is available gnssClockFlags must contain HAS_DRIFT.
*
- * This value is mandatory if the receiver has estimated GNSS time.
+ * This value is mandatory if the receiver has estimated GPS time.
*/
double driftNsps;
@@ -228,15 +238,15 @@
* second).
* The uncertainty is represented as an absolute (single sided) value.
*
- * If the data is available gnssClockFlags must contain
- * HAS_DRIFT_UNCERTAINTY. If GNSS has computed a position fix this
- * field is mandatory and must be populated.
+ * If the data is available gnssClockFlags must contain HAS_DRIFT_UNCERTAINTY.
+ *
+ * This value is mandatory if the receiver has estimated GPS time.
*/
double driftUncertaintyNsps;
/**
- * When there are any discontinuities in the HW clock, this field is
- * mandatory.
+ * This field must be incremented, when there are discontinuities in the
+ * hardware clock.
*
* A "discontinuity" is meant to cover the case of a switch from one source
* of clock to another. A single free-running crystal oscillator (XO)
@@ -262,6 +272,8 @@
* as this avoids the need to use (waste) a GNSS measurement to fully
* re-solve for the GNSS clock bias and drift, when using the accompanying
* measurements, from consecutive GnssData reports.
+ *
+ * This value is mandatory.
*/
uint32_t hwClockDiscontinuityCount;
@@ -280,17 +292,26 @@
/**
* A set of flags indicating the validity of the fields in this data
* structure.
+ *
+ * Fields for which there is no corresponding flag must be filled in
+ * with a valid value. For convenience, these are marked as mandatory.
+ *
+ * Others fields may have invalid information in them, if not marked as
+ * valid by the corresponding bit in flags.
*/
bitfield<GnssMeasurementFlags> flags;
/**
* Satellite vehicle ID number, as defined in GnssSvInfo::svid
- * This is a mandatory value.
+ *
+ * This value is mandatory.
*/
int16_t svid;
/**
* Defines the constellation of the given SV.
+ *
+ * This value is mandatory.
*/
GnssConstellationType constellation;
@@ -302,8 +323,10 @@
* measurement time = GnssClock::timeNs + timeOffsetNs
*
* It provides an individual time-stamp for the measurement, and allows
- * sub-nanosecond accuracy.
- * This is a mandatory value.
+ * sub-nanosecond accuracy. It may be zero if all measurements are
+ * aligned to a common time.
+ *
+ * This value is mandatory.
*/
double timeOffsetNs;
@@ -313,7 +336,7 @@
* Based on the sync state, the 'received GNSS tow' field must be interpreted
* accordingly.
*
- * This is a mandatory value.
+ * This value is mandatory.
*/
bitfield<GnssMeasurementState> state;
@@ -413,7 +436,7 @@
* Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
* It contains the measured C/N0 value for the signal at the antenna port.
*
- * This is a mandatory value.
+ * This value is mandatory.
*/
double cN0DbHz;
@@ -449,7 +472,7 @@
* 1-Sigma uncertainty of the pseudorangeRateMps.
* The uncertainty is represented as an absolute (single sided) value.
*
- * This is a mandatory value.
+ * This value is mandatory.
*/
double pseudorangeRateUncertaintyMps;
@@ -457,7 +480,7 @@
* Accumulated delta range's state. It indicates whether ADR is reset or
* there is a cycle slip(indicating loss of lock).
*
- * This is a mandatory value.
+ * This value is mandatory.
*/
bitfield<GnssAccumulatedDeltaRangeState> accumulatedDeltaRangeState;
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index 405990e..1f8bbdb 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -11,12 +11,14 @@
"IAccessor.hal",
"IClientManager.hal",
"IConnection.hal",
+ "IObserver.hal",
],
interfaces: [
"android.hidl.base@1.0",
],
types: [
"Buffer",
+ "BufferInvalidationMessage",
"BufferStatus",
"BufferStatusMessage",
"ResultStatus",
diff --git a/media/bufferpool/2.0/IAccessor.hal b/media/bufferpool/2.0/IAccessor.hal
index ab7c02d..66707fe 100644
--- a/media/bufferpool/2.0/IAccessor.hal
+++ b/media/bufferpool/2.0/IAccessor.hal
@@ -17,6 +17,7 @@
package android.hardware.media.bufferpool@2.0;
import IConnection;
+import IObserver;
/**
* IAccessor creates IConnection which is used from IClientManager in order to
* use functionality of the specified buffer pool.
@@ -49,6 +50,13 @@
* made and kept private. Also part of transaction ID is a sender ID in
* order to prevent fake transactions from other clients. This must be
* verified with an FMQ message from a buffer pool.
+
+ * @param observer The buffer pool event observer from the client.
+ * Observer is provided to ensure FMQ messages are processed even when
+ * client processes are idle. Buffer invalidation caused by
+ * reconfiguration does not call observer. Buffer invalidation caused
+ * by termination of pipeline call observer in order to ensure
+ * invalidation is done after pipeline completion.
*
* @return status The status of the call.
* OK - A connection is made successfully.
@@ -64,7 +72,7 @@
* @return fromFmqDesc FMQ descriptor. The descriptor is used to
* receive buffer invalidation messages from the buffer pool.
*/
- connect()
+ connect(IObserver observer)
generates (ResultStatus status, IConnection connection,
int64_t connectionId,
fmq_sync<BufferStatusMessage> toFmqDesc,
diff --git a/media/bufferpool/2.0/IObserver.hal b/media/bufferpool/2.0/IObserver.hal
new file mode 100644
index 0000000..a998836
--- /dev/null
+++ b/media/bufferpool/2.0/IObserver.hal
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 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.media.bufferpool@2.0;
+
+/**
+ * IObserver listens on notifications from the buffer pool. On receiving
+ * notifications, FMQ messages from the specific buffer pool which are already
+ * in the FMQ are processed.
+ */
+interface IObserver {
+
+ /**
+ * The specific buffer pool sent a message to the client. Calling this
+ * method from the buffer pool enforces a buffer pool client process the
+ * message.
+ *
+ * @param connectionId the connection Id of the specific buffer pool client
+ */
+ oneway onMessage(int64_t connectionId);
+};
diff --git a/media/bufferpool/2.0/types.hal b/media/bufferpool/2.0/types.hal
index 456e4aa..597e7b3 100644
--- a/media/bufferpool/2.0/types.hal
+++ b/media/bufferpool/2.0/types.hal
@@ -65,6 +65,8 @@
TRANSFER_OK = 7,
/** Buffer transaction failure. */
TRANSFER_ERROR = 8,
+ /** Buffer invalidation ack. */
+ INVALIDATION_ACK = 9,
};
/**
@@ -98,6 +100,7 @@
* buffers as soon as possible upon receiving the message.
*/
struct BufferInvalidationMessage {
+ uint32_t messageId;
/**
* Buffers from fromBufferId to toBufferId must be invalidated.
* fromBufferId is inclusive, but toBufferId is not inclusive.
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index 9cc23a2..aff4cf3 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -26,6 +26,36 @@
*/
interface IDevice extends @1.1::IDevice {
/**
+ * Get the version string of the driver implementation.
+ *
+ * The version string must be a unique token among the set of version strings of
+ * drivers of a specific device. The token identifies the device driver's
+ * implementation. The token must not be confused with the feature level which is solely
+ * defined by the interface version. This API is opaque to the Android framework, but the
+ * Android framework may use the information for debugging or to pass on to NNAPI applications.
+ *
+ * Application developers sometimes have specific requirements to ensure good user experiences,
+ * and they need more information to make intelligent decisions when the Android framework cannot.
+ * For example, combined with the device name and other information, the token can help
+ * NNAPI applications filter devices based on their needs:
+ * - An application demands a certain level of performance, but a specific version of
+ * the driver cannot meet that requirement because of a performance regression.
+ * The application can blacklist the driver based on the version provided.
+ * - An application has a minimum precision requirement, but certain versions of
+ * the driver cannot meet that requirement because of bugs or certain optimizations.
+ * The application can filter out versions of these drivers.
+ *
+ * @return status Error status returned from querying the version string. Must be:
+ * - NONE if the query was successful
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if the query resulted in an
+ * unspecified error
+ * @return version The version string of the device implementation.
+ * Must have nonzero length
+ */
+ getVersionString() generates (ErrorStatus status, string version);
+
+ /**
* Gets the supported operations in a model.
*
* getSupportedOperations indicates which operations of a model are fully
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index d2dea1d..eb3ebd3 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -37,6 +37,14 @@
EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
}
+// device version test
+TEST_F(NeuralnetworksHidlTest, GetDeviceVersionStringTest) {
+ Return<void> ret = device->getVersionString([](ErrorStatus status, const hidl_string& version) {
+ EXPECT_EQ(ErrorStatus::NONE, status);
+ EXPECT_LT(0, version.size());
+ });
+ EXPECT_TRUE(ret.isOk());
+}
} // namespace functional
} // namespace vts
} // namespace V1_2
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index 9424a85..6a9b1d0 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -20,6 +20,7 @@
],
types: [
"AccessNetwork",
+ "DataProfileInfo",
"DataRegStateResult",
"EmergencyNumber",
"EmergencyNumberSource",
diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal
index 2b14488..dde9d71 100644
--- a/radio/1.3/IRadio.hal
+++ b/radio/1.3/IRadio.hal
@@ -16,7 +16,7 @@
package android.hardware.radio@1.3;
-import @1.0::DataProfileInfo;
+import @1.3::DataProfileInfo;
import @1.0::Dial;
import @1.2::DataRequestReason;
import @1.2::IRadio;
@@ -56,13 +56,7 @@
* @param accessNetwork The access network to setup the data call. If the data connection cannot
* be established on the specified access network, the setup request must be failed.
* @param dataProfileInfo Data profile info.
- * @param modemCognitive Indicates that the requested profile has previously been provided via
- * setDataProfile().
* @param roamingAllowed Indicates whether or not data roaming is allowed by the user.
- * @param isRoaming Indicates whether or not the framework has requested this setupDataCall for
- * a roaming network. The 'protocol' parameter in the old RIL API must be filled
- * accordingly based on the roaming condition. Note this is for backward compatibility with
- * the old radio modem. The modem must not use this param for any other reason.
* @param reason The request reason. Must be DataRequestReason.NORMAL or
* DataRequestReason.HANDOVER.
* @param addresses If the reason is DataRequestReason.HANDOVER, this indicates the list of link
@@ -82,8 +76,28 @@
* Note this API is same as 1.2 version except using the 1.3 AccessNetwork as the input param.
*/
oneway setupDataCall_1_3(int32_t serial, AccessNetwork accessNetwork,
- DataProfileInfo dataProfileInfo, bool modemCognitive, bool roamingAllowed,
- bool isRoaming, DataRequestReason reason, vec<string> addresses, vec<string> dnses);
+ DataProfileInfo dataProfileInfo, bool roamingAllowed,
+ DataRequestReason reason, vec<string> addresses, vec<string> dnses);
+
+ /**
+ * Set an apn to initial attach network
+ *
+ * @param serial Serial number of request.
+ * @param dataProfileInfo data profile containing APN settings
+ *
+ * Response callback is IRadioResponse.setInitialAttachApnResponse()
+ */
+ oneway setInitialAttachApn_1_3(int32_t serial, DataProfileInfo dataProfileInfo);
+
+ /**
+ * Send data profiles of the current carrier to the modem.
+ *
+ * @param serial Serial number of request.
+ * @param profiles Array of DataProfile to set.
+ *
+ * Response callback is IRadioResponse.setDataProfileResponse()
+ */
+ oneway setDataProfile_1_3(int32_t serial, vec<DataProfileInfo> profiles);
/**
* Initiate emergency voice call, with zero or more emergency service category(s).
diff --git a/radio/1.3/types.hal b/radio/1.3/types.hal
index 09202a5..a41f4b2 100644
--- a/radio/1.3/types.hal
+++ b/radio/1.3/types.hal
@@ -16,6 +16,11 @@
package android.hardware.radio@1.3;
+import @1.0::ApnAuthType;
+import @1.0::ApnTypes;
+import @1.0::DataProfileId;
+import @1.0::DataProfileInfoType;
+import @1.0::RadioAccessFamily;
import @1.0::RegState;
import @1.2::AccessNetwork;
import @1.2::CellIdentity;
@@ -160,3 +165,71 @@
LteVopsInfo lteVopsInfo; // LTE network capability
} vopsInfo;
};
+
+/**
+ * Overwritten from @1.0::DataProfileInfo in order to deprecate 'mvnoType', 'mvnoMatchData',
+ * 'maxConnsTime', and 'maxConns'. In the future, this must be extended instead of overwritten.
+ * Added 'preferred' and 'persistent' in this version.
+ */
+struct DataProfileInfo {
+ /** id of the data profile */
+ DataProfileId profileId;
+
+ /** The APN name */
+ string apn;
+
+ /**
+ * One of the PDP_type values in TS 27.007 section 10.1.1. For example, "IP", "IPV6", "IPV4V6",
+ * or "PPP".
+ */
+ string protocol;
+
+ /**
+ * one of the PDP_type values in TS 27.007 section 10.1.1 used on roaming network. For example,
+ * "IP", "IPV6", "IPV4V6", or "PPP".
+ */
+ string roamingProtocol;
+
+ /** APN authentication type */
+ ApnAuthType authType;
+
+ /** The username for APN, or empty string */
+ string user;
+
+ /** The password for APN, or empty string */
+ string password;
+
+ /** Data profile technology type */
+ DataProfileInfoType type;
+
+ /**
+ * The required wait time in seconds after a successful UE initiated disconnect of a given PDN
+ * connection before the device can send a new PDN connection request for that given PDN.
+ */
+ int32_t waitTime;
+
+ /** True to enable the profile, false to disable */
+ bool enabled;
+
+ /** Supported APN types bitmap. See ApnTypes for the value of each bit. */
+ bitfield<ApnTypes> supportedApnTypesBitmap;
+
+ /** The bearer bitmap. See RadioAccessFamily for the value of each bit. */
+ bitfield<RadioAccessFamily> bearerBitmap;
+
+ /** Maximum transmission unit (MTU) size in bytes */
+ int32_t mtu;
+
+ /**
+ * True if this data profile was used to bring up the last default (i.e internet) data
+ * connection successfully.
+ */
+ bool preferred;
+
+ /**
+ * If true, modem must persist this data profile and profileId must not be
+ * set to DataProfileId.INVALID. If the same data profile exists, this data profile must
+ * overwrite it.
+ */
+ bool persistent;
+};
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 0ea400e..6563e3c 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -18,13 +18,14 @@
name: "VtsHalSensorsV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
- "GrallocWrapper.cpp",
+ "SensorsHidlEnvironmentV1_0.cpp",
"VtsHalSensorsV1_0TargetTest.cpp"
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.sensors@1.0",
+ "VtsHalSensorsTargetTestUtils",
],
}
diff --git a/sensors/1.0/vts/functional/GrallocWrapper.cpp b/sensors/1.0/vts/functional/GrallocWrapper.cpp
deleted file mode 100644
index e422d62..0000000
--- a/sensors/1.0/vts/functional/GrallocWrapper.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocWrapper"
-
-#include "GrallocWrapper.h"
-
-#include <utils/Log.h>
-
-namespace android {
-
-GrallocWrapper::GrallocWrapper() { init(); }
-
-void GrallocWrapper::init() {
- mAllocator = allocator2::IAllocator::getService();
- if (mAllocator == nullptr) {
- ALOGE("Failed to get allocator service");
- }
-
- mMapper = mapper2::IMapper::getService();
- if (mMapper == nullptr) {
- ALOGE("Failed to get mapper service");
- }
- if (mMapper->isRemote()) {
- ALOGE("Mapper is not in passthrough mode");
- }
-}
-
-GrallocWrapper::~GrallocWrapper() {
- for (auto bufferHandle : mClonedBuffers) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
- native_handle_close(buffer);
- native_handle_delete(buffer);
- }
- mClonedBuffers.clear();
-
- for (auto bufferHandle : mImportedBuffers) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
- if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
- ALOGE("Failed to free buffer %p", buffer);
- }
- }
- mImportedBuffers.clear();
-}
-
-sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
- return mAllocator;
-}
-
-std::string GrallocWrapper::dumpDebugInfo() {
- std::string debugInfo;
- mAllocator->dumpDebugInfo(
- [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
- return debugInfo;
-}
-
-const native_handle_t* GrallocWrapper::cloneBuffer(
- const hardware::hidl_handle& rawHandle) {
- const native_handle_t* bufferHandle =
- native_handle_clone(rawHandle.getNativeHandle());
-
- if (bufferHandle) {
- mClonedBuffers.insert(bufferHandle);
- }
- return bufferHandle;
-}
-
-std::vector<const native_handle_t*> GrallocWrapper::allocate(
- const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import,
- uint32_t* outStride) {
- std::vector<const native_handle_t*> bufferHandles;
- bufferHandles.reserve(count);
- mAllocator->allocate(
- descriptor, count,
- [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
- if (mapper2::Error::NONE != tmpError) {
- ALOGE("Failed to allocate buffers");
- }
- if (count != tmpBuffers.size()) {
- ALOGE("Invalid buffer array");
- }
-
- for (uint32_t i = 0; i < count; i++) {
- if (import) {
- bufferHandles.push_back(importBuffer(tmpBuffers[i]));
- } else {
- bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
- }
- }
-
- if (outStride) {
- *outStride = tmpStride;
- }
- });
-
- return bufferHandles;
-}
-
-const native_handle_t* GrallocWrapper::allocate(
- const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
- uint32_t* outStride) {
- mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
- ALOGE("QQ");
- auto buffers = allocate(descriptor, 1, import, outStride);
- return buffers[0];
-}
-
-sp<mapper2::IMapper> GrallocWrapper::getMapper() const { return mMapper; }
-
-mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
- const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
- mapper2::BufferDescriptor descriptor;
- mMapper->createDescriptor(
- descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to create descriptor");
- }
- descriptor = tmpDescriptor;
- });
-
- return descriptor;
-}
-
-const native_handle_t* GrallocWrapper::importBuffer(
- const hardware::hidl_handle& rawHandle) {
- const native_handle_t* bufferHandle = nullptr;
- mMapper->importBuffer(
- rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
- }
- bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
- });
-
- if (bufferHandle) {
- mImportedBuffers.insert(bufferHandle);
- }
-
- return bufferHandle;
-}
-
-void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
- if (mImportedBuffers.erase(bufferHandle)) {
- mapper2::Error error = mMapper->freeBuffer(buffer);
- if (error != mapper2::Error::NONE) {
- ALOGE("Failed to free %p", buffer);
- }
- } else {
- mClonedBuffers.erase(bufferHandle);
- native_handle_close(buffer);
- native_handle_delete(buffer);
- }
-}
-
-void* GrallocWrapper::lock(const native_handle_t* bufferHandle,
- uint64_t cpuUsage,
- const mapper2::IMapper::Rect& accessRegion,
- int acquireFence) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
- NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
- hardware::hidl_handle acquireFenceHandle;
- if (acquireFence >= 0) {
- auto h = native_handle_init(acquireFenceStorage, 1, 0);
- h->data[0] = acquireFence;
- acquireFenceHandle = h;
- }
-
- void* data = nullptr;
- mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpData) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to lock buffer %p", buffer);
- }
- data = tmpData;
- });
-
- if (acquireFence >= 0) {
- close(acquireFence);
- }
-
- return data;
-}
-
-int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
- int releaseFence = -1;
- mMapper->unlock(buffer, [&](const auto& tmpError,
- const auto& tmpReleaseFence) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to unlock buffer %p", buffer);
- }
-
- auto fenceHandle = tmpReleaseFence.getNativeHandle();
- if (fenceHandle) {
- if (fenceHandle->numInts != 0) {
- ALOGE("Invalid fence handle %p", fenceHandle);
- }
- if (fenceHandle->numFds == 1) {
- releaseFence = dup(fenceHandle->data[0]);
- if (releaseFence < 0){
- ALOGE("Failed to dup fence fd");
- }
- } else {
- if (fenceHandle->numFds != 0) {
- ALOGE("Invalid fence handle %p", fenceHandle);
- }
- }
- }
- });
-
- return releaseFence;
-}
-
-} // namespace android
diff --git a/sensors/1.0/vts/functional/GrallocWrapper.h b/sensors/1.0/vts/functional/GrallocWrapper.h
deleted file mode 100644
index e506fe1..0000000
--- a/sensors/1.0/vts/functional/GrallocWrapper.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GRALLO_WRAPPER_H_
-#define GRALLO_WRAPPER_H_
-
-#include <unordered_set>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-
-namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
-namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;
-
-namespace android {
-
-// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
-class GrallocWrapper {
- public:
- GrallocWrapper();
- ~GrallocWrapper();
-
- sp<allocator2::IAllocator> getAllocator() const;
- sp<mapper2::IMapper> getMapper() const;
-
- std::string dumpDebugInfo();
-
- // When import is false, this simply calls IAllocator::allocate. When import
- // is true, the returned buffers are also imported into the mapper.
- //
- // Either case, the returned buffers must be freed with freeBuffer.
- std::vector<const native_handle_t*> allocate(
- const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import = true,
- uint32_t* outStride = nullptr);
- const native_handle_t* allocate(
- const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
- uint32_t* outStride = nullptr);
-
- mapper2::BufferDescriptor createDescriptor(
- const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);
-
- const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
- void freeBuffer(const native_handle_t* bufferHandle);
-
- // We use fd instead of hardware::hidl_handle in these functions to pass fences
- // in and out of the mapper. The ownership of the fd is always transferred
- // with each of these functions.
- void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
- const mapper2::IMapper::Rect& accessRegion, int acquireFence);
-
- int unlock(const native_handle_t* bufferHandle);
-
- private:
- void init();
- const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);
-
- sp<allocator2::IAllocator> mAllocator;
- sp<mapper2::IMapper> mMapper;
-
- // Keep track of all cloned and imported handles. When a test fails with
- // ASSERT_*, the destructor will free the handles for the test.
- std::unordered_set<const native_handle_t*> mClonedBuffers;
- std::unordered_set<const native_handle_t*> mImportedBuffers;
-};
-
-} // namespace android
-#endif // GRALLO_WRAPPER_H_
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
new file mode 100644
index 0000000..f8b021e
--- /dev/null
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2018 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 "SensorsHidlEnvironmentV1_0.h"
+
+#include <log/log.h>
+
+#include <vector>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::sensors::V1_0::ISensors;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+
+bool SensorsHidlEnvironmentV1_0::resetHal() {
+ // wait upto 100ms * 10 = 1s for hidl service.
+ constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
+
+ std::string step;
+ bool succeed = false;
+ for (size_t retry = 10; retry > 0; --retry) {
+ // this do ... while is for easy error handling
+ do {
+ step = "getService()";
+ sensors = ISensors::getService(
+ SensorsHidlEnvironmentV1_0::Instance()->getServiceName<ISensors>());
+ if (sensors == nullptr) {
+ break;
+ }
+
+ step = "poll() check";
+ // Poke ISensor service. If it has lingering connection from previous generation of
+ // system server, it will kill itself. There is no intention to handle the poll result,
+ // which will be done since the size is 0.
+ if (!sensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
+ break;
+ }
+
+ step = "getSensorList";
+ std::vector<SensorInfo> sensorList;
+ if (!sensors
+ ->getSensorsList([&](const hidl_vec<SensorInfo>& list) {
+ sensorList.reserve(list.size());
+ for (size_t i = 0; i < list.size(); ++i) {
+ sensorList.push_back(list[i]);
+ }
+ })
+ .isOk()) {
+ break;
+ }
+
+ // stop each sensor individually
+ step = "stop each sensor";
+ bool ok = true;
+ for (const auto& i : sensorList) {
+ if (!sensors->activate(i.sensorHandle, false).isOk()) {
+ ok = false;
+ break;
+ }
+ }
+ if (!ok) {
+ break;
+ }
+
+ // mark it done
+ step = "done";
+ succeed = true;
+ } while (0);
+
+ if (succeed) {
+ return true;
+ }
+
+ // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
+ ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
+ std::this_thread::sleep_for(RETRY_DELAY);
+ }
+
+ sensors = nullptr;
+ return false;
+}
+
+void SensorsHidlEnvironmentV1_0::startPollingThread() {
+ stopThread = false;
+ pollThread = std::thread(pollingThread, this, std::ref(stopThread));
+ events.reserve(128);
+}
+
+void SensorsHidlEnvironmentV1_0::pollingThread(SensorsHidlEnvironmentV1_0* env,
+ std::atomic_bool& stop) {
+ ALOGD("polling thread start");
+
+ while (!stop) {
+ env->sensors->poll(
+ 64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
+ if (result != Result::OK ||
+ (events.size() == 0 && dynamicSensorsAdded.size() == 0) || stop) {
+ stop = true;
+ return;
+ }
+
+ for (const auto& e : events) {
+ env->addEvent(e);
+ }
+ });
+ }
+ ALOGD("polling thread end");
+}
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
new file mode 100644
index 0000000..0a9e59f
--- /dev/null
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
+#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
+
+#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/1.0/types.h>
+#include <utils/StrongPointer.h>
+
+#include <atomic>
+#include <memory>
+
+using ::android::sp;
+
+class SensorsHidlTest;
+class SensorsHidlEnvironmentV1_0 : public SensorsHidlEnvironmentBase {
+ public:
+ using Event = ::android::hardware::sensors::V1_0::Event;
+ // get the test environment singleton
+ static SensorsHidlEnvironmentV1_0* Instance() {
+ static SensorsHidlEnvironmentV1_0* instance = new SensorsHidlEnvironmentV1_0();
+ return instance;
+ }
+
+ virtual void registerTestServices() override {
+ registerTestService<android::hardware::sensors::V1_0::ISensors>();
+ }
+
+ private:
+ friend SensorsHidlTest;
+ // sensors hidl service
+ sp<android::hardware::sensors::V1_0::ISensors> sensors;
+
+ SensorsHidlEnvironmentV1_0() {}
+
+ bool resetHal() override;
+ void startPollingThread() override;
+ static void pollingThread(SensorsHidlEnvironmentV1_0* env, std::atomic_bool& stop);
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV1_0);
+};
+
+#endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index c18eedd..47308e1 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -15,583 +15,66 @@
*/
#define LOG_TAG "sensors_hidl_hal_test"
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-#include <android-base/logging.h>
+
+#include "SensorsHidlEnvironmentV1_0.h"
+#include "sensors-vts-utils/SensorsHidlTestBase.h"
+
#include <android/hardware/sensors/1.0/ISensors.h>
#include <android/hardware/sensors/1.0/types.h>
-#include <cutils/ashmem.h>
-#include <hardware/sensors.h> // for sensor type strings
#include <log/log.h>
#include <utils/SystemClock.h>
-#include "GrallocWrapper.h"
-#include <algorithm>
#include <cinttypes>
-#include <cmath>
-#include <memory>
-#include <mutex>
-#include <thread>
-#include <unordered_set>
#include <vector>
-#include <sys/mman.h>
-#include <unistd.h>
-
-using ::android::GrallocWrapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using ::android::hardware::hidl_string;
using ::android::sp;
using namespace ::android::hardware::sensors::V1_0;
-// Test environment for sensors
-class SensorsHidlTest;
-class SensorsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static SensorsHidlEnvironment* Instance() {
- static SensorsHidlEnvironment* instance = new SensorsHidlEnvironment;
- return instance;
- }
-
- virtual void HidlSetUp() override;
- virtual void HidlTearDown() override;
-
- virtual void registerTestServices() override { registerTestService<ISensors>(); }
-
- // Get and clear all events collected so far (like "cat" shell command).
- // If output is nullptr, it clears all collected events.
- void catEvents(std::vector<Event>* output);
-
- // set sensor event collection status
- void setCollection(bool enable);
-
- private:
- friend SensorsHidlTest;
- // sensors hidl service
- sp<ISensors> sensors;
-
- SensorsHidlEnvironment() {}
-
- void addEvent(const Event& ev);
- void startPollingThread();
- void resetHal();
- static void pollingThread(SensorsHidlEnvironment* env, std::shared_ptr<bool> stop);
-
- bool collectionEnabled;
- std::shared_ptr<bool> stopThread;
- std::thread pollThread;
- std::vector<Event> events;
- std::mutex events_mutex;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironment);
-};
-
-void SensorsHidlEnvironment::HidlSetUp() {
- resetHal();
-
- ASSERT_NE(sensors, nullptr) << "sensors is nullptr, cannot get hidl service";
-
- collectionEnabled = false;
- startPollingThread();
-
- // In case framework just stopped for test and there is sensor events in the pipe,
- // wait some time for those events to be cleared to avoid them messing up the test.
- std::this_thread::sleep_for(std::chrono::seconds(3));
-}
-
-void SensorsHidlEnvironment::HidlTearDown() {
- if (stopThread) {
- *stopThread = true;
- }
- pollThread.detach();
-}
-
-void SensorsHidlEnvironment::resetHal() {
- // wait upto 100ms * 10 = 1s for hidl service.
- constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
-
- std::string step;
- bool succeed = false;
- for (size_t retry = 10; retry > 0; --retry) {
- // this do ... while is for easy error handling
- do {
- step = "getService()";
- sensors = ISensors::getService(
- SensorsHidlEnvironment::Instance()->getServiceName<ISensors>());
- if (sensors == nullptr) {
- break;
- }
-
- step = "poll() check";
- // Poke ISensor service. If it has lingering connection from previous generation of
- // system server, it will kill itself. There is no intention to handle the poll result,
- // which will be done since the size is 0.
- if(!sensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) {
- break;
- }
-
- step = "getSensorList";
- std::vector<SensorInfo> sensorList;
- if (!sensors->getSensorsList(
- [&] (const ::android::hardware::hidl_vec<SensorInfo> &list) {
- sensorList.reserve(list.size());
- for (size_t i = 0; i < list.size(); ++i) {
- sensorList.push_back(list[i]);
- }
- }).isOk()) {
- break;
- }
-
- // stop each sensor individually
- step = "stop each sensor";
- bool ok = true;
- for (const auto &i : sensorList) {
- if (!sensors->activate(i.sensorHandle, false).isOk()) {
- ok = false;
- break;
- }
- }
- if (!ok) {
- break;
- }
-
- // mark it done
- step = "done";
- succeed = true;
- } while(0);
-
- if (succeed) {
- return;
- }
-
- // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
- ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
- std::this_thread::sleep_for(RETRY_DELAY);
- }
-
- sensors = nullptr;
-}
-
-void SensorsHidlEnvironment::catEvents(std::vector<Event>* output) {
- std::lock_guard<std::mutex> lock(events_mutex);
- if (output) {
- output->insert(output->end(), events.begin(), events.end());
- }
- events.clear();
-}
-
-void SensorsHidlEnvironment::setCollection(bool enable) {
- std::lock_guard<std::mutex> lock(events_mutex);
- collectionEnabled = enable;
-}
-
-void SensorsHidlEnvironment::addEvent(const Event& ev) {
- std::lock_guard<std::mutex> lock(events_mutex);
- if (collectionEnabled) {
- events.push_back(ev);
- }
-}
-
-void SensorsHidlEnvironment::startPollingThread() {
- stopThread = std::shared_ptr<bool>(new bool(false));
- pollThread = std::thread(pollingThread, this, stopThread);
- events.reserve(128);
-}
-
-void SensorsHidlEnvironment::pollingThread(
- SensorsHidlEnvironment* env, std::shared_ptr<bool> stop) {
- ALOGD("polling thread start");
- bool needExit = *stop;
-
- while(!needExit) {
- env->sensors->poll(64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
- if (result != Result::OK
- || (events.size() == 0 && dynamicSensorsAdded.size() == 0)
- || *stop) {
- needExit = true;
- return;
- }
-
- for (const auto& e : events) {
- env->addEvent(e);
- }
- });
- }
- ALOGD("polling thread end");
-}
-
-class SensorsTestSharedMemory {
- public:
- static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
- SharedMemInfo getSharedMemInfo() const;
- char * getBuffer() const;
- std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
- virtual ~SensorsTestSharedMemory();
- private:
- SensorsTestSharedMemory(SharedMemType type, size_t size);
-
- SharedMemType mType;
- native_handle_t* mNativeHandle;
- size_t mSize;
- char* mBuffer;
- std::unique_ptr<GrallocWrapper> mGrallocWrapper;
-
- DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
-};
-
-SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const {
- SharedMemInfo mem = {
- .type = mType,
- .format = SharedMemFormat::SENSORS_EVENT,
- .size = static_cast<uint32_t>(mSize),
- .memoryHandle = mNativeHandle
- };
- return mem;
-}
-
-char * SensorsTestSharedMemory::getBuffer() const {
- return mBuffer;
-}
-
-std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
-
- constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
- constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
- constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
- constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
- constexpr size_t kOffsetAtomicCounter =
- static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
- constexpr size_t kOffsetTimestamp = static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
- constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
-
- std::vector<Event> events;
- std::vector<float> data(16);
-
- while (offset + kEventSize <= mSize) {
- int64_t atomicCounter = *reinterpret_cast<uint32_t *>(mBuffer + offset + kOffsetAtomicCounter);
- if (atomicCounter <= lastCounter) {
- ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter, lastCounter);
- break;
- }
-
- int32_t size = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetSize);
- if (size != kEventSize) {
- // unknown error, events parsed may be wrong, remove all
- events.clear();
- break;
- }
-
- int32_t token = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetToken);
- int32_t type = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetType);
- int64_t timestamp = *reinterpret_cast<int64_t *>(mBuffer + offset + kOffsetTimestamp);
-
- ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32 ", timestamp %" PRId64,
- offset, atomicCounter, token, type, timestamp);
-
- Event event = {
- .timestamp = timestamp,
- .sensorHandle = token,
- .sensorType = static_cast<SensorType>(type),
- };
- event.u.data = android::hardware::hidl_array<float, 16>
- (reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
-
- events.push_back(event);
-
- lastCounter = atomicCounter;
- offset += kEventSize;
- }
-
- return events;
-}
-
-SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size)
- : mType(type), mSize(0), mBuffer(nullptr) {
- native_handle_t *handle = nullptr;
- char *buffer = nullptr;
- switch(type) {
- case SharedMemType::ASHMEM: {
- int fd;
- handle = ::native_handle_create(1 /*nFds*/, 0/*nInts*/);
- if (handle != nullptr) {
- handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
- if (handle->data[0] > 0) {
- // memory is pinned by default
- buffer = static_cast<char *>
- (::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
- if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
- break;
- }
- ::native_handle_close(handle);
- }
- ::native_handle_delete(handle);
- handle = nullptr;
- }
- break;
- }
- case SharedMemType::GRALLOC: {
- mGrallocWrapper = std::make_unique<GrallocWrapper>();
- if (mGrallocWrapper->getAllocator() == nullptr || mGrallocWrapper->getMapper() == nullptr) {
- break;
- }
- using android::hardware::graphics::common::V1_0::BufferUsage;
- using android::hardware::graphics::common::V1_0::PixelFormat;
- mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
- .width = static_cast<uint32_t>(size),
- .height = 1,
- .layerCount = 1,
- .usage = static_cast<uint64_t> (BufferUsage::SENSOR_DIRECT_DATA |
- BufferUsage::CPU_READ_OFTEN),
- .format = PixelFormat::BLOB
- };
-
- handle = const_cast<native_handle_t *>(mGrallocWrapper->allocate(buf_desc_info));
- if (handle != nullptr) {
- mapper2::IMapper::Rect region{0, 0,
- static_cast<int32_t>(buf_desc_info.width),
- static_cast<int32_t>(buf_desc_info.height)};
- buffer = static_cast<char *>
- (mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
- if (buffer != nullptr) {
- break;
- }
- mGrallocWrapper->freeBuffer(handle);
- handle = nullptr;
- }
- break;
- }
- default:
- break;
- }
-
- if (buffer != nullptr) {
- mNativeHandle = handle;
- mSize = size;
- mBuffer = buffer;
- }
-}
-
-SensorsTestSharedMemory::~SensorsTestSharedMemory() {
- switch(mType) {
- case SharedMemType::ASHMEM: {
- if (mSize != 0) {
- ::munmap(mBuffer, mSize);
- mBuffer = nullptr;
-
- ::native_handle_close(mNativeHandle);
- ::native_handle_delete(mNativeHandle);
-
- mNativeHandle = nullptr;
- mSize = 0;
- }
- break;
- }
- case SharedMemType::GRALLOC: {
- if (mSize != 0) {
- mGrallocWrapper->unlock(mNativeHandle);
- mGrallocWrapper->freeBuffer(mNativeHandle);
-
- mNativeHandle = nullptr;
- mSize = 0;
- }
- break;
- }
- default: {
- if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
- ALOGE("SensorsTestSharedMemory %p not properly destructed: "
- "type %d, native handle %p, size %zu, buffer %p",
- this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
- }
- break;
- }
- }
-}
-
-SensorsTestSharedMemory* SensorsTestSharedMemory::create(SharedMemType type, size_t size) {
- constexpr size_t kMaxSize = 128*1024*1024; // sensor test should not need more than 128M
- if (size == 0 || size >= kMaxSize) {
- return nullptr;
- }
-
- auto m = new SensorsTestSharedMemory(type, size);
- if (m->mSize != size || m->mBuffer == nullptr) {
- delete m;
- m = nullptr;
- }
- return m;
-}
-
-class SensorEventsChecker {
- public:
- virtual bool check(const std::vector<Event> &events, std::string *out) const = 0;
- virtual ~SensorEventsChecker() {}
-};
-
-class NullChecker : public SensorEventsChecker {
- public:
- virtual bool check(const std::vector<Event> &, std::string *) const {
- return true;
- }
-};
-
-class SensorEventPerEventChecker : public SensorEventsChecker {
- public:
- virtual bool checkEvent(const Event &event, std::string *out) const = 0;
- virtual bool check(const std::vector<Event> &events, std::string *out) const {
- for (const auto &e : events) {
- if (!checkEvent(e, out)) {
- return false;
- }
- }
- return true;
- }
-};
-
-class Vec3NormChecker : public SensorEventPerEventChecker {
- public:
- Vec3NormChecker(float min, float max) : mRange(min, max) {}
- static Vec3NormChecker byNominal(float nominal, float allowedError) {
- return Vec3NormChecker(nominal - allowedError, nominal + allowedError);
- }
-
- virtual bool checkEvent(const Event &event, std::string *out) const {
- Vec3 v = event.u.vec3;
- float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
- if (norm < mRange.first || norm > mRange.second) {
- if (out != nullptr) {
- std::ostringstream ss;
- ss << "Event @ " << event.timestamp << " (" << v.x << ", " << v.y << ", " << v.z << ")"
- << " has norm " << norm << ", which is beyond range"
- << " [" << mRange.first << ", " << mRange.second << "]";
- *out = ss.str();
- }
- return false;
- }
- return true;
- }
- protected:
- std::pair<float, float> mRange;
-};
-
// The main test class for SENSORS HIDL HAL.
-class SensorsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- public:
- virtual void SetUp() override {
- }
- virtual void TearDown() override {
- // stop all sensors
- for (auto s : mSensorHandles) {
- S()->activate(s, false);
+class SensorsHidlTest : public SensorsHidlTestBase {
+ protected:
+ SensorInfo defaultSensorByType(SensorType type) override;
+ std::vector<SensorInfo> getSensorsList();
+ // implementation wrapper
+ Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override {
+ return S()->getSensorsList(_hidl_cb);
}
- mSensorHandles.clear();
- // stop all direct report and channels
- for (auto c : mDirectChannelHandles) {
- // disable all reports
- S()->configDirectReport(-1, c, RateLevel::STOP, [] (auto, auto){});
- S()->unregisterDirectChannel(c);
+ Return<Result> activate(int32_t sensorHandle, bool enabled) override;
+
+ Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) override {
+ return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
}
- mDirectChannelHandles.clear();
- }
- protected:
- SensorInfo defaultSensorByType(SensorType type);
- std::vector<SensorInfo> getSensorsList();
- std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
- bool clearBeforeStart = true, bool changeCollection = true);
+ Return<Result> flush(int32_t sensorHandle) override { return S()->flush(sensorHandle); }
- // implementation wrapper
- Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) {
- return S()->getSensorsList(_hidl_cb);
- }
+ Return<Result> injectSensorData(const Event& event) override {
+ return S()->injectSensorData(event);
+ }
- Return<Result> activate(
- int32_t sensorHandle, bool enabled);
+ Return<void> registerDirectChannel(const SharedMemInfo& mem,
+ ISensors::registerDirectChannel_cb _hidl_cb) override;
- Return<Result> batch(
- int32_t sensorHandle,
- int64_t samplingPeriodNs,
- int64_t maxReportLatencyNs) {
- return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
- }
+ Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+ return S()->unregisterDirectChannel(channelHandle);
+ }
- Return<Result> flush(int32_t sensorHandle) {
- return S()->flush(sensorHandle);
- }
+ Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+ ISensors::configDirectReport_cb _hidl_cb) override {
+ return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+ }
- Return<Result> injectSensorData(const Event& event) {
- return S()->injectSensorData(event);
- }
+ inline sp<ISensors>& S() { return SensorsHidlEnvironmentV1_0::Instance()->sensors; }
- Return<void> registerDirectChannel(
- const SharedMemInfo& mem, ISensors::registerDirectChannel_cb _hidl_cb);
-
- Return<Result> unregisterDirectChannel(int32_t channelHandle) {
- return S()->unregisterDirectChannel(channelHandle);
- }
-
- Return<void> configDirectReport(
- int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
- ISensors::configDirectReport_cb _hidl_cb) {
- return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
- }
-
- inline sp<ISensors>& S() {
- return SensorsHidlEnvironment::Instance()->sensors;
- }
-
- inline static SensorFlagBits extractReportMode(uint64_t flag) {
- return (SensorFlagBits) (flag
- & ((uint64_t) SensorFlagBits::CONTINUOUS_MODE
- | (uint64_t) SensorFlagBits::ON_CHANGE_MODE
- | (uint64_t) SensorFlagBits::ONE_SHOT_MODE
- | (uint64_t) SensorFlagBits::SPECIAL_REPORTING_MODE));
- }
-
- inline static bool isMetaSensorType(SensorType type) {
- return (type == SensorType::META_DATA
- || type == SensorType::DYNAMIC_SENSOR_META
- || type == SensorType::ADDITIONAL_INFO);
- }
-
- inline static bool isValidType(SensorType type) {
- return (int32_t) type > 0;
- }
-
- void testStreamingOperation(SensorType type,
- std::chrono::nanoseconds samplingPeriod,
- std::chrono::seconds duration,
- const SensorEventsChecker &checker);
- void testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow = true);
- void testBatchingOperation(SensorType type);
- void testDirectReportOperation(
- SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker);
-
- static void assertTypeMatchStringType(SensorType type, const hidl_string& stringType);
- static void assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode);
- static void assertDelayMatchReportMode(
- int32_t minDelay, int32_t maxDelay, SensorFlagBits reportMode);
- static SensorFlagBits expectedReportModeForType(SensorType type);
- static bool isDirectReportRateSupported(SensorInfo sensor, RateLevel rate);
- static bool isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type);
-
- // checkers
- static const Vec3NormChecker sAccelNormChecker;
- static const Vec3NormChecker sGyroNormChecker;
-
- // all sensors and direct channnels used
- std::unordered_set<int32_t> mSensorHandles;
- std::unordered_set<int32_t> mDirectChannelHandles;
+ SensorsHidlEnvironmentBase* getEnvironment() override {
+ return SensorsHidlEnvironmentV1_0::Instance();
+ }
};
-const Vec3NormChecker SensorsHidlTest::sAccelNormChecker(
- Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f/*m/s^2*/));
-const Vec3NormChecker SensorsHidlTest::sGyroNormChecker(
- Vec3NormChecker::byNominal(0.f, 0.1f/*rad/s*/));
-
Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
// If activating a sensor, add the handle in a set so that when test fails it can be turned off.
// The handle is not removed when it is deactivating on purpose so that it is not necessary to
@@ -618,195 +101,6 @@
return Void();
}
-std::vector<Event> SensorsHidlTest::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
- bool clearBeforeStart, bool changeCollection) {
- std::vector<Event> events;
- constexpr useconds_t SLEEP_GRANULARITY = 100*1000; //granularity 100 ms
-
- ALOGI("collect max of %zu events for %d us, clearBeforeStart %d",
- nEventLimit, timeLimitUs, clearBeforeStart);
-
- if (changeCollection) {
- SensorsHidlEnvironment::Instance()->setCollection(true);
- }
- if (clearBeforeStart) {
- SensorsHidlEnvironment::Instance()->catEvents(nullptr);
- }
-
- while (timeLimitUs > 0) {
- useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
- usleep(duration);
- timeLimitUs -= duration;
-
- SensorsHidlEnvironment::Instance()->catEvents(&events);
- if (events.size() >= nEventLimit) {
- break;
- }
- ALOGV("time to go = %d, events to go = %d",
- (int)timeLimitUs, (int)(nEventLimit - events.size()));
- }
-
- if (changeCollection) {
- SensorsHidlEnvironment::Instance()->setCollection(false);
- }
- return events;
-}
-
-void SensorsHidlTest::assertTypeMatchStringType(SensorType type, const hidl_string& stringType) {
-
- if (type >= SensorType::DEVICE_PRIVATE_BASE) {
- return;
- }
-
- switch (type) {
-#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
- case SensorType::type: ASSERT_STREQ(SENSOR_STRING_TYPE_ ## type, stringType.c_str()); break;
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
- CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
- default:
- FAIL() << "Type " << static_cast<int>(type) << " in android defined range is not checked, "
- << "stringType = " << stringType;
-#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
- }
-}
-
-void SensorsHidlTest::assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode) {
- if (type >= SensorType::DEVICE_PRIVATE_BASE) {
- return;
- }
-
- SensorFlagBits expected = expectedReportModeForType(type);
-
- ASSERT_TRUE(expected == (SensorFlagBits) -1 || expected == reportMode)
- << "reportMode=" << static_cast<int>(reportMode)
- << "expected=" << static_cast<int>(expected);
-}
-
-void SensorsHidlTest::assertDelayMatchReportMode(
- int32_t minDelay, int32_t maxDelay, SensorFlagBits reportMode) {
- switch(reportMode) {
- case SensorFlagBits::CONTINUOUS_MODE:
- ASSERT_LT(0, minDelay);
- ASSERT_LE(0, maxDelay);
- break;
- case SensorFlagBits::ON_CHANGE_MODE:
- ASSERT_LE(0, minDelay);
- ASSERT_LE(0, maxDelay);
- break;
- case SensorFlagBits::ONE_SHOT_MODE:
- ASSERT_EQ(-1, minDelay);
- ASSERT_EQ(0, maxDelay);
- break;
- case SensorFlagBits::SPECIAL_REPORTING_MODE:
- // do not enforce anything for special reporting mode
- break;
- default:
- FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
- }
-}
-
-// return -1 means no expectation for this type
-SensorFlagBits SensorsHidlTest::expectedReportModeForType(SensorType type) {
- switch (type) {
- case SensorType::ACCELEROMETER:
- case SensorType::ACCELEROMETER_UNCALIBRATED:
- case SensorType::GYROSCOPE:
- case SensorType::MAGNETIC_FIELD:
- case SensorType::ORIENTATION:
- case SensorType::PRESSURE:
- case SensorType::TEMPERATURE:
- case SensorType::GRAVITY:
- case SensorType::LINEAR_ACCELERATION:
- case SensorType::ROTATION_VECTOR:
- case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
- case SensorType::GAME_ROTATION_VECTOR:
- case SensorType::GYROSCOPE_UNCALIBRATED:
- case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
- case SensorType::POSE_6DOF:
- case SensorType::HEART_BEAT:
- return SensorFlagBits::CONTINUOUS_MODE;
-
- case SensorType::LIGHT:
- case SensorType::PROXIMITY:
- case SensorType::RELATIVE_HUMIDITY:
- case SensorType::AMBIENT_TEMPERATURE:
- case SensorType::HEART_RATE:
- case SensorType::DEVICE_ORIENTATION:
- case SensorType::STEP_COUNTER:
- case SensorType::LOW_LATENCY_OFFBODY_DETECT:
- return SensorFlagBits::ON_CHANGE_MODE;
-
- case SensorType::SIGNIFICANT_MOTION:
- case SensorType::WAKE_GESTURE:
- case SensorType::GLANCE_GESTURE:
- case SensorType::PICK_UP_GESTURE:
- case SensorType::MOTION_DETECT:
- case SensorType::STATIONARY_DETECT:
- return SensorFlagBits::ONE_SHOT_MODE;
-
- case SensorType::STEP_DETECTOR:
- case SensorType::TILT_DETECTOR:
- case SensorType::WRIST_TILT_GESTURE:
- case SensorType::DYNAMIC_SENSOR_META:
- return SensorFlagBits::SPECIAL_REPORTING_MODE;
-
- default:
- ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
- return (SensorFlagBits)-1;
- }
-}
-
-bool SensorsHidlTest::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) {
- unsigned int r =
- static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT)
- >> static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
- return r >= static_cast<unsigned int>(rate);
-}
-
-bool SensorsHidlTest::isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type) {
- switch (type) {
- case SharedMemType::ASHMEM:
- return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0;
- case SharedMemType::GRALLOC:
- return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0;
- default:
- return false;
- }
-}
-
SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) {
SensorInfo ret;
@@ -951,69 +245,6 @@
ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
}
-void SensorsHidlTest::testStreamingOperation(SensorType type,
- std::chrono::nanoseconds samplingPeriod,
- std::chrono::seconds duration,
- const SensorEventsChecker &checker) {
- std::vector<Event> events;
- std::vector<Event> sensorEvents;
-
- const int64_t samplingPeriodInNs = samplingPeriod.count();
- const int64_t batchingPeriodInNs = 0; // no batching
- const useconds_t minTimeUs = std::chrono::microseconds(duration).count();
- const size_t minNEvent = duration / samplingPeriod;
-
- SensorInfo sensor = defaultSensorByType(type);
-
- if (!isValidType(sensor.type)) {
- // no default sensor of this type
- return;
- }
-
- if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) {
- // rate not supported
- return;
- }
-
- int32_t handle = sensor.sensorHandle;
-
- ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
- ASSERT_EQ(activate(handle, 1), Result::OK);
- events = collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/);
- ASSERT_EQ(activate(handle, 0), Result::OK);
-
- ALOGI("Collected %zu samples", events.size());
-
- ASSERT_GT(events.size(), 0u);
-
- bool handleMismatchReported = false;
- bool metaSensorTypeErrorReported = false;
- for (auto & e : events) {
- if (e.sensorType == type) {
- // avoid generating hundreds of error
- if (!handleMismatchReported) {
- EXPECT_EQ(e.sensorHandle, handle)
- << (handleMismatchReported = true,
- "Event of the same type must come from the sensor registered");
- }
- sensorEvents.push_back(e);
- } else {
- // avoid generating hundreds of error
- if (!metaSensorTypeErrorReported) {
- EXPECT_TRUE(isMetaSensorType(e.sensorType))
- << (metaSensorTypeErrorReported = true,
- "Only meta types are allowed besides the type registered");
- }
- }
- }
-
- std::string s;
- EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
-
- EXPECT_GE(sensorEvents.size(),
- minNEvent / 2); // make sure returned events are not all meta
-}
-
// Test if sensor hal can do UI speed accelerometer streaming properly
TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
testStreamingOperation(SensorType::ACCELEROMETER,
@@ -1086,103 +317,6 @@
NullChecker());
}
-void SensorsHidlTest::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) {
- std::vector<Event> events1, events2;
-
- constexpr int64_t batchingPeriodInNs = 0; // no batching
- constexpr int64_t collectionTimeoutUs = 60000000; // 60s
- constexpr size_t minNEvent = 50;
-
- SensorInfo sensor = defaultSensorByType(type);
-
- if (!isValidType(sensor.type)) {
- // no default sensor of this type
- return;
- }
-
- int32_t handle = sensor.sensorHandle;
- int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
- int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll;
-
- if (minSamplingPeriodInNs == maxSamplingPeriodInNs) {
- // only support single rate
- return;
- }
-
- int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
- int64_t secondCollectionPeriod = !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
-
- // first collection
- ASSERT_EQ(batch(handle, firstCollectionPeriod, batchingPeriodInNs), Result::OK);
- ASSERT_EQ(activate(handle, 1), Result::OK);
-
- usleep(500000); // sleep 0.5 sec to wait for change rate to happen
- events1 = collectEvents(collectionTimeoutUs, minNEvent);
-
- // second collection, without stop sensor
- ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
-
- usleep(500000); // sleep 0.5 sec to wait for change rate to happen
- events2 = collectEvents(collectionTimeoutUs, minNEvent);
-
- // end of collection, stop sensor
- ASSERT_EQ(activate(handle, 0), Result::OK);
-
- ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size());
-
- ASSERT_GT(events1.size(), 0u);
- ASSERT_GT(events2.size(), 0u);
-
- int64_t minDelayAverageInterval, maxDelayAverageInterval;
- std::vector<Event> &minDelayEvents(fastToSlow ? events1 : events2);
- std::vector<Event> &maxDelayEvents(fastToSlow ? events2 : events1);
-
- size_t nEvent = 0;
- int64_t prevTimestamp = -1;
- int64_t timestampInterval = 0;
- for (auto & e : minDelayEvents) {
- if (e.sensorType == type) {
- ASSERT_EQ(e.sensorHandle, handle);
- if (prevTimestamp > 0) {
- timestampInterval += e.timestamp - prevTimestamp;
- }
- prevTimestamp = e.timestamp;
- ++ nEvent;
- }
- }
- ASSERT_GT(nEvent, 2u);
- minDelayAverageInterval = timestampInterval / (nEvent - 1);
-
- nEvent = 0;
- prevTimestamp = -1;
- timestampInterval = 0;
- for (auto & e : maxDelayEvents) {
- if (e.sensorType == type) {
- ASSERT_EQ(e.sensorHandle, handle);
- if (prevTimestamp > 0) {
- timestampInterval += e.timestamp - prevTimestamp;
- }
- prevTimestamp = e.timestamp;
- ++ nEvent;
- }
- }
- ASSERT_GT(nEvent, 2u);
- maxDelayAverageInterval = timestampInterval / (nEvent - 1);
-
- // change of rate is significant.
- ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64,
- minDelayAverageInterval, maxDelayAverageInterval);
- EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10);
-
- // fastest rate sampling time is close to spec
- EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
- minSamplingPeriodInNs / 10);
-
- // slowest rate sampling time is close to spec
- EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
- maxSamplingPeriodInNs / 10);
-}
-
// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
@@ -1201,74 +335,6 @@
testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
}
-void SensorsHidlTest::testBatchingOperation(SensorType type) {
- std::vector<Event> events;
-
- constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
- constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000;
-
- SensorInfo sensor = defaultSensorByType(type);
-
- if (!isValidType(sensor.type)) {
- // no default sensor of this type
- return;
- }
-
- int32_t handle = sensor.sensorHandle;
- int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
- uint32_t minFifoCount = sensor.fifoReservedEventCount;
- int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs;
-
- if (batchingPeriodInNs < oneSecondInNs) {
- // batching size too small to test reliably
- return;
- }
-
- batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs);
-
- ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000));
-
- int64_t allowedBatchDeliverTimeNs =
- std::max(oneSecondInNs, batchingPeriodInNs / 10);
-
- ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK);
- ASSERT_EQ(activate(handle, 1), Result::OK);
-
- usleep(500000); // sleep 0.5 sec to wait for initialization
- ASSERT_EQ(flush(handle), Result::OK);
-
- // wait for 80% of the reserved batching period
- // there should not be any significant amount of events
- // since collection is not enabled all events will go down the drain
- usleep(batchingPeriodInNs / 1000 * 8 / 10);
-
- SensorsHidlEnvironment::Instance()->setCollection(true);
- // clean existing collections
- collectEvents(0 /*timeLimitUs*/, 0/*nEventLimit*/,
- true /*clearBeforeStart*/, false /*change collection*/);
-
- // 0.8 + 0.2 times the batching period
- usleep(batchingPeriodInNs / 1000 * 8 / 10);
- ASSERT_EQ(flush(handle), Result::OK);
-
- // plus some time for the event to deliver
- events = collectEvents(allowedBatchDeliverTimeNs / 1000,
- minFifoCount, false /*clearBeforeStart*/, false /*change collection*/);
-
- SensorsHidlEnvironment::Instance()->setCollection(false);
- ASSERT_EQ(activate(handle, 0), Result::OK);
-
- size_t nEvent = 0;
- for (auto & e : events) {
- if (e.sensorType == type && e.sensorHandle == handle) {
- ++ nEvent;
- }
- }
-
- // at least reach 90% of advertised capacity
- ASSERT_GT(nEvent, (size_t)(minFifoCount * 9 / 10));
-}
-
// Test if sensor hal can do accelerometer batching properly
TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
testBatchingOperation(SensorType::ACCELEROMETER);
@@ -1284,124 +350,6 @@
testBatchingOperation(SensorType::MAGNETIC_FIELD);
}
-void SensorsHidlTest::testDirectReportOperation(
- SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker) {
- constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
- constexpr size_t kNEvent = 4096;
- constexpr size_t kMemSize = kEventSize * kNEvent;
-
- constexpr float kNormalNominal = 50;
- constexpr float kFastNominal = 200;
- constexpr float kVeryFastNominal = 800;
-
- constexpr float kNominalTestTimeSec = 1.f;
- constexpr float kMaxTestTimeSec = kNominalTestTimeSec + 0.5f; // 0.5 second for initialization
-
- SensorInfo sensor = defaultSensorByType(type);
-
- if (!isValidType(sensor.type)) {
- // no default sensor of this type
- return;
- }
-
- if (!isDirectReportRateSupported(sensor, rate)) {
- return;
- }
-
- if (!isDirectChannelTypeSupported(sensor, memType)) {
- return;
- }
-
- std::unique_ptr<SensorsTestSharedMemory>
- mem(SensorsTestSharedMemory::create(memType, kMemSize));
- ASSERT_NE(mem, nullptr);
-
- char* buffer = mem->getBuffer();
- // fill memory with data
- for (size_t i = 0; i < kMemSize; ++i) {
- buffer[i] = '\xcc';
- }
-
- int32_t channelHandle;
- registerDirectChannel(mem->getSharedMemInfo(),
- [&channelHandle] (auto result, auto channelHandle_) {
- ASSERT_EQ(result, Result::OK);
- channelHandle = channelHandle_;
- });
-
- // check memory is zeroed
- for (size_t i = 0; i < kMemSize; ++i) {
- ASSERT_EQ(buffer[i], '\0');
- }
-
- int32_t eventToken;
- configDirectReport(sensor.sensorHandle, channelHandle, rate,
- [&eventToken] (auto result, auto token) {
- ASSERT_EQ(result, Result::OK);
- eventToken = token;
- });
-
- usleep(static_cast<useconds_t>(kMaxTestTimeSec * 1e6f));
- auto events = mem->parseEvents();
-
- // find norminal rate
- float nominalFreq = 0.f;
- switch (rate) {
- case RateLevel::NORMAL:
- nominalFreq = kNormalNominal;
- break;
- case RateLevel::FAST:
- nominalFreq = kFastNominal;
- break;
- case RateLevel::VERY_FAST:
- nominalFreq = kVeryFastNominal;
- break;
- case RateLevel::STOP:
- FAIL();
- }
-
- // allowed to be between 55% and 220% of nominal freq
- ASSERT_GT(events.size(), static_cast<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec));
- ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec));
-
- int64_t lastTimestamp = 0;
- bool typeErrorReported = false;
- bool tokenErrorReported = false;
- bool timestampErrorReported = false;
- std::vector<Event> sensorEvents;
- for (auto &e : events) {
- if (!tokenErrorReported) {
- EXPECT_EQ(eventToken, e.sensorHandle)
- << (tokenErrorReported = true,
- "Event token does not match that retured from configDirectReport");
- }
-
- if (isMetaSensorType(e.sensorType)) {
- continue;
- }
- sensorEvents.push_back(e);
-
- if (!typeErrorReported) {
- EXPECT_EQ(type, e.sensorType)
- << (typeErrorReported = true,
- "Type in event does not match type of sensor registered.");
- }
- if (!timestampErrorReported) {
- EXPECT_GT(e.timestamp, lastTimestamp)
- << (timestampErrorReported = true, "Timestamp not monotonically increasing");
- }
- lastTimestamp = e.timestamp;
- }
-
- std::string s;
- EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
-
- // stop sensor and unregister channel
- configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
- [](auto result, auto) { EXPECT_EQ(result, Result::OK); });
- EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
-}
-
// Test sensor event direct report with ashmem for accel sensor at normal rate
TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
@@ -1511,11 +459,11 @@
}
int main(int argc, char **argv) {
- ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- SensorsHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- return status;
+ ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV1_0::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ SensorsHidlEnvironmentV1_0::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGI("Test result = %d", status);
+ return status;
}
// vim: set ts=2 sw=2
diff --git a/sensors/common/vts/OWNERS b/sensors/common/vts/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/common/vts/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
new file mode 100644
index 0000000..95df425
--- /dev/null
+++ b/sensors/common/vts/utils/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "VtsHalSensorsTargetTestUtils",
+ srcs: [
+ "GrallocWrapper.cpp",
+ "SensorsHidlEnvironmentBase.cpp",
+ "SensorsHidlTestBase.cpp",
+ "SensorsTestSharedMemory.cpp",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ local_include_dirs: [
+ "include/sensors-vts-utils",
+ ],
+ static_libs: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.sensors@1.0",
+ "VtsHalHidlTargetTestBase",
+ ],
+}
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
new file mode 100644
index 0000000..7bed16d
--- /dev/null
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GrallocWrapper"
+
+#include "GrallocWrapper.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+GrallocWrapper::GrallocWrapper() {
+ init();
+}
+
+void GrallocWrapper::init() {
+ mAllocator = allocator2::IAllocator::getService();
+ if (mAllocator == nullptr) {
+ ALOGE("Failed to get allocator service");
+ }
+
+ mMapper = mapper2::IMapper::getService();
+ if (mMapper == nullptr) {
+ ALOGE("Failed to get mapper service");
+ }
+ if (mMapper->isRemote()) {
+ ALOGE("Mapper is not in passthrough mode");
+ }
+}
+
+GrallocWrapper::~GrallocWrapper() {
+ for (auto bufferHandle : mClonedBuffers) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ native_handle_close(buffer);
+ native_handle_delete(buffer);
+ }
+ mClonedBuffers.clear();
+
+ for (auto bufferHandle : mImportedBuffers) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
+ ALOGE("Failed to free buffer %p", buffer);
+ }
+ }
+ mImportedBuffers.clear();
+}
+
+sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
+ return mAllocator;
+}
+
+std::string GrallocWrapper::dumpDebugInfo() {
+ std::string debugInfo;
+ mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+ return debugInfo;
+}
+
+const native_handle_t* GrallocWrapper::cloneBuffer(const hardware::hidl_handle& rawHandle) {
+ const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
+
+ if (bufferHandle) {
+ mClonedBuffers.insert(bufferHandle);
+ }
+ return bufferHandle;
+}
+
+std::vector<const native_handle_t*> GrallocWrapper::allocate(
+ const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) {
+ std::vector<const native_handle_t*> bufferHandles;
+ bufferHandles.reserve(count);
+ mAllocator->allocate(descriptor, count,
+ [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
+ if (mapper2::Error::NONE != tmpError) {
+ ALOGE("Failed to allocate buffers");
+ }
+ if (count != tmpBuffers.size()) {
+ ALOGE("Invalid buffer array");
+ }
+
+ for (uint32_t i = 0; i < count; i++) {
+ if (import) {
+ bufferHandles.push_back(importBuffer(tmpBuffers[i]));
+ } else {
+ bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
+ }
+ }
+
+ if (outStride) {
+ *outStride = tmpStride;
+ }
+ });
+
+ return bufferHandles;
+}
+
+const native_handle_t* GrallocWrapper::allocate(
+ const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
+ uint32_t* outStride) {
+ mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+ auto buffers = allocate(descriptor, 1, import, outStride);
+ return buffers[0];
+}
+
+sp<mapper2::IMapper> GrallocWrapper::getMapper() const {
+ return mMapper;
+}
+
+mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
+ const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
+ mapper2::BufferDescriptor descriptor;
+ mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+ if (tmpError != mapper2::Error::NONE) {
+ ALOGE("Failed to create descriptor");
+ }
+ descriptor = tmpDescriptor;
+ });
+
+ return descriptor;
+}
+
+const native_handle_t* GrallocWrapper::importBuffer(const hardware::hidl_handle& rawHandle) {
+ const native_handle_t* bufferHandle = nullptr;
+ mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+ if (tmpError != mapper2::Error::NONE) {
+ ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
+ }
+ bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+ });
+
+ if (bufferHandle) {
+ mImportedBuffers.insert(bufferHandle);
+ }
+
+ return bufferHandle;
+}
+
+void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ if (mImportedBuffers.erase(bufferHandle)) {
+ mapper2::Error error = mMapper->freeBuffer(buffer);
+ if (error != mapper2::Error::NONE) {
+ ALOGE("Failed to free %p", buffer);
+ }
+ } else {
+ mClonedBuffers.erase(bufferHandle);
+ native_handle_close(buffer);
+ native_handle_delete(buffer);
+ }
+}
+
+void* GrallocWrapper::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const mapper2::IMapper::Rect& accessRegion, int acquireFence) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+ hardware::hidl_handle acquireFenceHandle;
+ if (acquireFence >= 0) {
+ auto h = native_handle_init(acquireFenceStorage, 1, 0);
+ h->data[0] = acquireFence;
+ acquireFenceHandle = h;
+ }
+
+ void* data = nullptr;
+ mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpData) {
+ if (tmpError != mapper2::Error::NONE) {
+ ALOGE("Failed to lock buffer %p", buffer);
+ }
+ data = tmpData;
+ });
+
+ if (acquireFence >= 0) {
+ close(acquireFence);
+ }
+
+ return data;
+}
+
+int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ int releaseFence = -1;
+ mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+ if (tmpError != mapper2::Error::NONE) {
+ ALOGE("Failed to unlock buffer %p", buffer);
+ }
+
+ auto fenceHandle = tmpReleaseFence.getNativeHandle();
+ if (fenceHandle) {
+ if (fenceHandle->numInts != 0) {
+ ALOGE("Invalid fence handle %p", fenceHandle);
+ }
+ if (fenceHandle->numFds == 1) {
+ releaseFence = dup(fenceHandle->data[0]);
+ if (releaseFence < 0) {
+ ALOGE("Failed to dup fence fd");
+ }
+ } else {
+ if (fenceHandle->numFds != 0) {
+ ALOGE("Invalid fence handle %p", fenceHandle);
+ }
+ }
+ }
+ });
+
+ return releaseFence;
+}
+
+} // namespace android
diff --git a/sensors/common/vts/utils/OWNERS b/sensors/common/vts/utils/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/common/vts/utils/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
new file mode 100644
index 0000000..21c08d2
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 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 "SensorsHidlEnvironmentBase.h"
+
+void SensorsHidlEnvironmentBase::HidlSetUp() {
+ ASSERT_TRUE(resetHal()) << "could not get hidl service";
+
+ collectionEnabled = false;
+ startPollingThread();
+
+ // In case framework just stopped for test and there is sensor events in the pipe,
+ // wait some time for those events to be cleared to avoid them messing up the test.
+ std::this_thread::sleep_for(std::chrono::seconds(3));
+}
+
+void SensorsHidlEnvironmentBase::HidlTearDown() {
+ stopThread = true;
+ pollThread.detach();
+}
+
+void SensorsHidlEnvironmentBase::catEvents(std::vector<Event>* output) {
+ std::lock_guard<std::mutex> lock(events_mutex);
+ if (output) {
+ output->insert(output->end(), events.begin(), events.end());
+ }
+ events.clear();
+}
+
+void SensorsHidlEnvironmentBase::setCollection(bool enable) {
+ std::lock_guard<std::mutex> lock(events_mutex);
+ collectionEnabled = enable;
+}
+
+void SensorsHidlEnvironmentBase::addEvent(const Event& ev) {
+ std::lock_guard<std::mutex> lock(events_mutex);
+ if (collectionEnabled) {
+ events.push_back(ev);
+ }
+}
diff --git a/sensors/common/vts/utils/SensorsHidlTestBase.cpp b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
new file mode 100644
index 0000000..8497d82
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2018 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 "SensorsHidlTestBase.h"
+
+#include "sensors-vts-utils/GrallocWrapper.h"
+#include "sensors-vts-utils/SensorsTestSharedMemory.h"
+
+#include <hardware/sensors.h> // for sensor type strings
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+#include <cinttypes>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::sensors::V1_0;
+
+const Vec3NormChecker SensorsHidlTestBase::sAccelNormChecker(
+ Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f /*m/s^2*/));
+const Vec3NormChecker SensorsHidlTestBase::sGyroNormChecker(
+ Vec3NormChecker::byNominal(0.f, 0.1f /*rad/s*/));
+
+std::vector<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+ bool clearBeforeStart,
+ bool changeCollection) {
+ std::vector<Event> events;
+ constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000; // granularity 100 ms
+
+ ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs,
+ clearBeforeStart);
+
+ if (changeCollection) {
+ getEnvironment()->setCollection(true);
+ }
+ if (clearBeforeStart) {
+ getEnvironment()->catEvents(nullptr);
+ }
+
+ while (timeLimitUs > 0) {
+ useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
+ usleep(duration);
+ timeLimitUs -= duration;
+
+ getEnvironment()->catEvents(&events);
+ if (events.size() >= nEventLimit) {
+ break;
+ }
+ ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs,
+ (int)(nEventLimit - events.size()));
+ }
+
+ if (changeCollection) {
+ getEnvironment()->setCollection(false);
+ }
+ return events;
+}
+
+void SensorsHidlTestBase::assertTypeMatchStringType(SensorType type,
+ const hidl_string& stringType) {
+ if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+ return;
+ }
+
+ switch (type) {
+#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
+ case SensorType::type: \
+ ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \
+ break;
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
+ default:
+ FAIL() << "Type " << static_cast<int>(type)
+ << " in android defined range is not checked, "
+ << "stringType = " << stringType;
+#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
+ }
+}
+
+void SensorsHidlTestBase::assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode) {
+ if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+ return;
+ }
+
+ SensorFlagBits expected = expectedReportModeForType(type);
+
+ ASSERT_TRUE(expected == (SensorFlagBits)-1 || expected == reportMode)
+ << "reportMode=" << static_cast<int>(reportMode)
+ << "expected=" << static_cast<int>(expected);
+}
+
+void SensorsHidlTestBase::assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay,
+ SensorFlagBits reportMode) {
+ switch (reportMode) {
+ case SensorFlagBits::CONTINUOUS_MODE:
+ ASSERT_LT(0, minDelay);
+ ASSERT_LE(0, maxDelay);
+ break;
+ case SensorFlagBits::ON_CHANGE_MODE:
+ ASSERT_LE(0, minDelay);
+ ASSERT_LE(0, maxDelay);
+ break;
+ case SensorFlagBits::ONE_SHOT_MODE:
+ ASSERT_EQ(-1, minDelay);
+ ASSERT_EQ(0, maxDelay);
+ break;
+ case SensorFlagBits::SPECIAL_REPORTING_MODE:
+ // do not enforce anything for special reporting mode
+ break;
+ default:
+ FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
+ }
+}
+
+// return -1 means no expectation for this type
+SensorFlagBits SensorsHidlTestBase::expectedReportModeForType(SensorType type) {
+ switch (type) {
+ case SensorType::ACCELEROMETER:
+ case SensorType::ACCELEROMETER_UNCALIBRATED:
+ case SensorType::GYROSCOPE:
+ case SensorType::MAGNETIC_FIELD:
+ case SensorType::ORIENTATION:
+ case SensorType::PRESSURE:
+ case SensorType::TEMPERATURE:
+ case SensorType::GRAVITY:
+ case SensorType::LINEAR_ACCELERATION:
+ case SensorType::ROTATION_VECTOR:
+ case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+ case SensorType::GAME_ROTATION_VECTOR:
+ case SensorType::GYROSCOPE_UNCALIBRATED:
+ case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
+ case SensorType::POSE_6DOF:
+ case SensorType::HEART_BEAT:
+ return SensorFlagBits::CONTINUOUS_MODE;
+
+ case SensorType::LIGHT:
+ case SensorType::PROXIMITY:
+ case SensorType::RELATIVE_HUMIDITY:
+ case SensorType::AMBIENT_TEMPERATURE:
+ case SensorType::HEART_RATE:
+ case SensorType::DEVICE_ORIENTATION:
+ case SensorType::STEP_COUNTER:
+ case SensorType::LOW_LATENCY_OFFBODY_DETECT:
+ return SensorFlagBits::ON_CHANGE_MODE;
+
+ case SensorType::SIGNIFICANT_MOTION:
+ case SensorType::WAKE_GESTURE:
+ case SensorType::GLANCE_GESTURE:
+ case SensorType::PICK_UP_GESTURE:
+ case SensorType::MOTION_DETECT:
+ case SensorType::STATIONARY_DETECT:
+ return SensorFlagBits::ONE_SHOT_MODE;
+
+ case SensorType::STEP_DETECTOR:
+ case SensorType::TILT_DETECTOR:
+ case SensorType::WRIST_TILT_GESTURE:
+ case SensorType::DYNAMIC_SENSOR_META:
+ return SensorFlagBits::SPECIAL_REPORTING_MODE;
+
+ default:
+ ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
+ return (SensorFlagBits)-1;
+ }
+}
+
+bool SensorsHidlTestBase::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) {
+ unsigned int r = static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) >>
+ static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
+ return r >= static_cast<unsigned int>(rate);
+}
+
+bool SensorsHidlTestBase::isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type) {
+ switch (type) {
+ case SharedMemType::ASHMEM:
+ return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0;
+ case SharedMemType::GRALLOC:
+ return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0;
+ default:
+ return false;
+ }
+}
+
+void SensorsHidlTestBase::testDirectReportOperation(SensorType type, SharedMemType memType,
+ RateLevel rate,
+ const SensorEventsChecker& checker) {
+ constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+ constexpr size_t kNEvent = 4096;
+ constexpr size_t kMemSize = kEventSize * kNEvent;
+
+ constexpr float kNormalNominal = 50;
+ constexpr float kFastNominal = 200;
+ constexpr float kVeryFastNominal = 800;
+
+ constexpr float kNominalTestTimeSec = 1.f;
+ constexpr float kMaxTestTimeSec = kNominalTestTimeSec + 0.5f; // 0.5 second for initialization
+
+ SensorInfo sensor = defaultSensorByType(type);
+
+ if (!isValidType(sensor.type)) {
+ // no default sensor of this type
+ return;
+ }
+
+ if (!isDirectReportRateSupported(sensor, rate)) {
+ return;
+ }
+
+ if (!isDirectChannelTypeSupported(sensor, memType)) {
+ return;
+ }
+
+ std::unique_ptr<SensorsTestSharedMemory> mem(
+ SensorsTestSharedMemory::create(memType, kMemSize));
+ ASSERT_NE(mem, nullptr);
+
+ char* buffer = mem->getBuffer();
+ // fill memory with data
+ for (size_t i = 0; i < kMemSize; ++i) {
+ buffer[i] = '\xcc';
+ }
+
+ int32_t channelHandle;
+ registerDirectChannel(mem->getSharedMemInfo(),
+ [&channelHandle](auto result, auto channelHandle_) {
+ ASSERT_EQ(result, Result::OK);
+ channelHandle = channelHandle_;
+ });
+
+ // check memory is zeroed
+ for (size_t i = 0; i < kMemSize; ++i) {
+ ASSERT_EQ(buffer[i], '\0');
+ }
+
+ int32_t eventToken;
+ configDirectReport(sensor.sensorHandle, channelHandle, rate,
+ [&eventToken](auto result, auto token) {
+ ASSERT_EQ(result, Result::OK);
+ eventToken = token;
+ });
+
+ usleep(static_cast<useconds_t>(kMaxTestTimeSec * 1e6f));
+ auto events = mem->parseEvents();
+
+ // find norminal rate
+ float nominalFreq = 0.f;
+ switch (rate) {
+ case RateLevel::NORMAL:
+ nominalFreq = kNormalNominal;
+ break;
+ case RateLevel::FAST:
+ nominalFreq = kFastNominal;
+ break;
+ case RateLevel::VERY_FAST:
+ nominalFreq = kVeryFastNominal;
+ break;
+ case RateLevel::STOP:
+ FAIL();
+ }
+
+ // allowed to be between 55% and 220% of nominal freq
+ ASSERT_GT(events.size(), static_cast<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec));
+ ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec));
+
+ int64_t lastTimestamp = 0;
+ bool typeErrorReported = false;
+ bool tokenErrorReported = false;
+ bool timestampErrorReported = false;
+ std::vector<Event> sensorEvents;
+ for (auto& e : events) {
+ if (!tokenErrorReported) {
+ EXPECT_EQ(eventToken, e.sensorHandle)
+ << (tokenErrorReported = true,
+ "Event token does not match that retured from configDirectReport");
+ }
+
+ if (isMetaSensorType(e.sensorType)) {
+ continue;
+ }
+ sensorEvents.push_back(e);
+
+ if (!typeErrorReported) {
+ EXPECT_EQ(type, e.sensorType)
+ << (typeErrorReported = true,
+ "Type in event does not match type of sensor registered.");
+ }
+ if (!timestampErrorReported) {
+ EXPECT_GT(e.timestamp, lastTimestamp)
+ << (timestampErrorReported = true, "Timestamp not monotonically increasing");
+ }
+ lastTimestamp = e.timestamp;
+ }
+
+ std::string s;
+ EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
+
+ // stop sensor and unregister channel
+ configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
+ [](auto result, auto) { EXPECT_EQ(result, Result::OK); });
+ EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
+}
+
+void SensorsHidlTestBase::testStreamingOperation(SensorType type,
+ std::chrono::nanoseconds samplingPeriod,
+ std::chrono::seconds duration,
+ const SensorEventsChecker& checker) {
+ std::vector<Event> events;
+ std::vector<Event> sensorEvents;
+
+ const int64_t samplingPeriodInNs = samplingPeriod.count();
+ const int64_t batchingPeriodInNs = 0; // no batching
+ const useconds_t minTimeUs = std::chrono::microseconds(duration).count();
+ const size_t minNEvent = duration / samplingPeriod;
+
+ SensorInfo sensor = defaultSensorByType(type);
+
+ if (!isValidType(sensor.type)) {
+ // no default sensor of this type
+ return;
+ }
+
+ if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) {
+ // rate not supported
+ return;
+ }
+
+ int32_t handle = sensor.sensorHandle;
+
+ ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
+ ASSERT_EQ(activate(handle, 1), Result::OK);
+ events = collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/);
+ ASSERT_EQ(activate(handle, 0), Result::OK);
+
+ ALOGI("Collected %zu samples", events.size());
+
+ ASSERT_GT(events.size(), 0u);
+
+ bool handleMismatchReported = false;
+ bool metaSensorTypeErrorReported = false;
+ for (auto& e : events) {
+ if (e.sensorType == type) {
+ // avoid generating hundreds of error
+ if (!handleMismatchReported) {
+ EXPECT_EQ(e.sensorHandle, handle)
+ << (handleMismatchReported = true,
+ "Event of the same type must come from the sensor registered");
+ }
+ sensorEvents.push_back(e);
+ } else {
+ // avoid generating hundreds of error
+ if (!metaSensorTypeErrorReported) {
+ EXPECT_TRUE(isMetaSensorType(e.sensorType))
+ << (metaSensorTypeErrorReported = true,
+ "Only meta types are allowed besides the type registered");
+ }
+ }
+ }
+
+ std::string s;
+ EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
+
+ EXPECT_GE(sensorEvents.size(),
+ minNEvent / 2); // make sure returned events are not all meta
+}
+
+void SensorsHidlTestBase::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) {
+ std::vector<Event> events1, events2;
+
+ constexpr int64_t batchingPeriodInNs = 0; // no batching
+ constexpr int64_t collectionTimeoutUs = 60000000; // 60s
+ constexpr size_t minNEvent = 50;
+
+ SensorInfo sensor = defaultSensorByType(type);
+
+ if (!isValidType(sensor.type)) {
+ // no default sensor of this type
+ return;
+ }
+
+ int32_t handle = sensor.sensorHandle;
+ int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
+ int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll;
+
+ if (minSamplingPeriodInNs == maxSamplingPeriodInNs) {
+ // only support single rate
+ return;
+ }
+
+ int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
+ int64_t secondCollectionPeriod = !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
+
+ // first collection
+ ASSERT_EQ(batch(handle, firstCollectionPeriod, batchingPeriodInNs), Result::OK);
+ ASSERT_EQ(activate(handle, 1), Result::OK);
+
+ usleep(500000); // sleep 0.5 sec to wait for change rate to happen
+ events1 = collectEvents(collectionTimeoutUs, minNEvent);
+
+ // second collection, without stop sensor
+ ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
+
+ usleep(500000); // sleep 0.5 sec to wait for change rate to happen
+ events2 = collectEvents(collectionTimeoutUs, minNEvent);
+
+ // end of collection, stop sensor
+ ASSERT_EQ(activate(handle, 0), Result::OK);
+
+ ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size());
+
+ ASSERT_GT(events1.size(), 0u);
+ ASSERT_GT(events2.size(), 0u);
+
+ int64_t minDelayAverageInterval, maxDelayAverageInterval;
+ std::vector<Event>& minDelayEvents(fastToSlow ? events1 : events2);
+ std::vector<Event>& maxDelayEvents(fastToSlow ? events2 : events1);
+
+ size_t nEvent = 0;
+ int64_t prevTimestamp = -1;
+ int64_t timestampInterval = 0;
+ for (auto& e : minDelayEvents) {
+ if (e.sensorType == type) {
+ ASSERT_EQ(e.sensorHandle, handle);
+ if (prevTimestamp > 0) {
+ timestampInterval += e.timestamp - prevTimestamp;
+ }
+ prevTimestamp = e.timestamp;
+ ++nEvent;
+ }
+ }
+ ASSERT_GT(nEvent, 2u);
+ minDelayAverageInterval = timestampInterval / (nEvent - 1);
+
+ nEvent = 0;
+ prevTimestamp = -1;
+ timestampInterval = 0;
+ for (auto& e : maxDelayEvents) {
+ if (e.sensorType == type) {
+ ASSERT_EQ(e.sensorHandle, handle);
+ if (prevTimestamp > 0) {
+ timestampInterval += e.timestamp - prevTimestamp;
+ }
+ prevTimestamp = e.timestamp;
+ ++nEvent;
+ }
+ }
+ ASSERT_GT(nEvent, 2u);
+ maxDelayAverageInterval = timestampInterval / (nEvent - 1);
+
+ // change of rate is significant.
+ ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64, minDelayAverageInterval,
+ maxDelayAverageInterval);
+ EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10);
+
+ // fastest rate sampling time is close to spec
+ EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
+ minSamplingPeriodInNs / 10);
+
+ // slowest rate sampling time is close to spec
+ EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
+ maxSamplingPeriodInNs / 10);
+}
+
+void SensorsHidlTestBase::testBatchingOperation(SensorType type) {
+ std::vector<Event> events;
+
+ constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
+ constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000;
+
+ SensorInfo sensor = defaultSensorByType(type);
+
+ if (!isValidType(sensor.type)) {
+ // no default sensor of this type
+ return;
+ }
+
+ int32_t handle = sensor.sensorHandle;
+ int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
+ uint32_t minFifoCount = sensor.fifoReservedEventCount;
+ int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs;
+
+ if (batchingPeriodInNs < oneSecondInNs) {
+ // batching size too small to test reliably
+ return;
+ }
+
+ batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs);
+
+ ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000));
+
+ int64_t allowedBatchDeliverTimeNs = std::max(oneSecondInNs, batchingPeriodInNs / 10);
+
+ ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK);
+ ASSERT_EQ(activate(handle, 1), Result::OK);
+
+ usleep(500000); // sleep 0.5 sec to wait for initialization
+ ASSERT_EQ(flush(handle), Result::OK);
+
+ // wait for 80% of the reserved batching period
+ // there should not be any significant amount of events
+ // since collection is not enabled all events will go down the drain
+ usleep(batchingPeriodInNs / 1000 * 8 / 10);
+
+ getEnvironment()->setCollection(true);
+ // clean existing collections
+ collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/, true /*clearBeforeStart*/,
+ false /*change collection*/);
+
+ // 0.8 + 0.2 times the batching period
+ usleep(batchingPeriodInNs / 1000 * 8 / 10);
+ ASSERT_EQ(flush(handle), Result::OK);
+
+ // plus some time for the event to deliver
+ events = collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount,
+ false /*clearBeforeStart*/, false /*change collection*/);
+
+ getEnvironment()->setCollection(false);
+ ASSERT_EQ(activate(handle, 0), Result::OK);
+
+ size_t nEvent = 0;
+ for (auto& e : events) {
+ if (e.sensorType == type && e.sensorHandle == handle) {
+ ++nEvent;
+ }
+ }
+
+ // at least reach 90% of advertised capacity
+ ASSERT_GT(nEvent, (size_t)(minFifoCount * 9 / 10));
+}
diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
new file mode 100644
index 0000000..5096498
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2018 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 "SensorsTestSharedMemory.h"
+
+#include <log/log.h>
+
+#include <sys/mman.h>
+#include <cinttypes>
+
+using namespace ::android::hardware::sensors::V1_0;
+
+SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const {
+ SharedMemInfo mem = {.type = mType,
+ .format = SharedMemFormat::SENSORS_EVENT,
+ .size = static_cast<uint32_t>(mSize),
+ .memoryHandle = mNativeHandle};
+ return mem;
+}
+
+char* SensorsTestSharedMemory::getBuffer() const {
+ return mBuffer;
+}
+
+std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
+ constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+ constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
+ constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
+ constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
+ constexpr size_t kOffsetAtomicCounter =
+ static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
+ constexpr size_t kOffsetTimestamp = static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
+ constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
+
+ std::vector<Event> events;
+ std::vector<float> data(16);
+
+ while (offset + kEventSize <= mSize) {
+ int64_t atomicCounter =
+ *reinterpret_cast<uint32_t*>(mBuffer + offset + kOffsetAtomicCounter);
+ if (atomicCounter <= lastCounter) {
+ ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter,
+ lastCounter);
+ break;
+ }
+
+ int32_t size = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetSize);
+ if (size != kEventSize) {
+ // unknown error, events parsed may be wrong, remove all
+ events.clear();
+ break;
+ }
+
+ int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken);
+ int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType);
+ int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp);
+
+ ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32
+ ", timestamp %" PRId64,
+ offset, atomicCounter, token, type, timestamp);
+
+ Event event = {
+ .timestamp = timestamp,
+ .sensorHandle = token,
+ .sensorType = static_cast<SensorType>(type),
+ };
+ event.u.data = android::hardware::hidl_array<float, 16>(
+ reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
+
+ events.push_back(event);
+
+ lastCounter = atomicCounter;
+ offset += kEventSize;
+ }
+
+ return events;
+}
+
+SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size)
+ : mType(type), mSize(0), mBuffer(nullptr) {
+ native_handle_t* handle = nullptr;
+ char* buffer = nullptr;
+ switch (type) {
+ case SharedMemType::ASHMEM: {
+ int fd;
+ handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/);
+ if (handle != nullptr) {
+ handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
+ if (handle->data[0] > 0) {
+ // memory is pinned by default
+ buffer = static_cast<char*>(
+ ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
+ if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
+ break;
+ }
+ ::native_handle_close(handle);
+ }
+ ::native_handle_delete(handle);
+ handle = nullptr;
+ }
+ break;
+ }
+ case SharedMemType::GRALLOC: {
+ mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
+ if (mGrallocWrapper->getAllocator() == nullptr ||
+ mGrallocWrapper->getMapper() == nullptr) {
+ break;
+ }
+ using android::hardware::graphics::common::V1_0::BufferUsage;
+ using android::hardware::graphics::common::V1_0::PixelFormat;
+ mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
+ .width = static_cast<uint32_t>(size),
+ .height = 1,
+ .layerCount = 1,
+ .usage = static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA |
+ BufferUsage::CPU_READ_OFTEN),
+ .format = PixelFormat::BLOB};
+
+ handle = const_cast<native_handle_t*>(mGrallocWrapper->allocate(buf_desc_info));
+ if (handle != nullptr) {
+ mapper2::IMapper::Rect region{0, 0, static_cast<int32_t>(buf_desc_info.width),
+ static_cast<int32_t>(buf_desc_info.height)};
+ buffer = static_cast<char*>(
+ mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
+ if (buffer != nullptr) {
+ break;
+ }
+ mGrallocWrapper->freeBuffer(handle);
+ handle = nullptr;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (buffer != nullptr) {
+ mNativeHandle = handle;
+ mSize = size;
+ mBuffer = buffer;
+ }
+}
+
+SensorsTestSharedMemory::~SensorsTestSharedMemory() {
+ switch (mType) {
+ case SharedMemType::ASHMEM: {
+ if (mSize != 0) {
+ ::munmap(mBuffer, mSize);
+ mBuffer = nullptr;
+
+ ::native_handle_close(mNativeHandle);
+ ::native_handle_delete(mNativeHandle);
+
+ mNativeHandle = nullptr;
+ mSize = 0;
+ }
+ break;
+ }
+ case SharedMemType::GRALLOC: {
+ if (mSize != 0) {
+ mGrallocWrapper->unlock(mNativeHandle);
+ mGrallocWrapper->freeBuffer(mNativeHandle);
+
+ mNativeHandle = nullptr;
+ mSize = 0;
+ }
+ break;
+ }
+ default: {
+ if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
+ ALOGE(
+ "SensorsTestSharedMemory %p not properly destructed: "
+ "type %d, native handle %p, size %zu, buffer %p",
+ this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
+ }
+ break;
+ }
+ }
+}
+
+SensorsTestSharedMemory* SensorsTestSharedMemory::create(SharedMemType type, size_t size) {
+ constexpr size_t kMaxSize = 128 * 1024 * 1024; // sensor test should not need more than 128M
+ if (size == 0 || size >= kMaxSize) {
+ return nullptr;
+ }
+
+ auto m = new SensorsTestSharedMemory(type, size);
+ if (m->mSize != size || m->mBuffer == nullptr) {
+ delete m;
+ m = nullptr;
+ }
+ return m;
+}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
new file mode 100644
index 0000000..3bd73c3
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRALLO_WRAPPER_H_
+#define GRALLO_WRAPPER_H_
+
+#include <unordered_set>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
+namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;
+
+namespace android {
+
+// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
+class GrallocWrapper {
+ public:
+ GrallocWrapper();
+ ~GrallocWrapper();
+
+ sp<allocator2::IAllocator> getAllocator() const;
+ sp<mapper2::IMapper> getMapper() const;
+
+ std::string dumpDebugInfo();
+
+ // When import is false, this simply calls IAllocator::allocate. When import
+ // is true, the returned buffers are also imported into the mapper.
+ //
+ // Either case, the returned buffers must be freed with freeBuffer.
+ std::vector<const native_handle_t*> allocate(const mapper2::BufferDescriptor& descriptor,
+ uint32_t count, bool import = true,
+ uint32_t* outStride = nullptr);
+ const native_handle_t* allocate(const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo,
+ bool import = true, uint32_t* outStride = nullptr);
+
+ mapper2::BufferDescriptor createDescriptor(
+ const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);
+
+ const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
+ void freeBuffer(const native_handle_t* bufferHandle);
+
+ // We use fd instead of hardware::hidl_handle in these functions to pass fences
+ // in and out of the mapper. The ownership of the fd is always transferred
+ // with each of these functions.
+ void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const mapper2::IMapper::Rect& accessRegion, int acquireFence);
+
+ int unlock(const native_handle_t* bufferHandle);
+
+ private:
+ void init();
+ const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);
+
+ sp<allocator2::IAllocator> mAllocator;
+ sp<mapper2::IMapper> mMapper;
+
+ // Keep track of all cloned and imported handles. When a test fails with
+ // ASSERT_*, the destructor will free the handles for the test.
+ std::unordered_set<const native_handle_t*> mClonedBuffers;
+ std::unordered_set<const native_handle_t*> mImportedBuffers;
+};
+
+} // namespace android
+#endif // GRALLO_WRAPPER_H_
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h
new file mode 100644
index 0000000..b5daccc
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSOR_EVENTS_CHECKER_H
+#define ANDROID_SENSOR_EVENTS_CHECKER_H
+
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <cmath>
+
+class SensorEventsChecker {
+ public:
+ using Event = ::android::hardware::sensors::V1_0::Event;
+ virtual bool check(const std::vector<Event>& events, std::string* out) const = 0;
+ virtual ~SensorEventsChecker() {}
+};
+
+class NullChecker : public SensorEventsChecker {
+ public:
+ virtual bool check(const std::vector<Event>&, std::string*) const { return true; }
+};
+
+class SensorEventPerEventChecker : public SensorEventsChecker {
+ public:
+ virtual bool checkEvent(const Event& event, std::string* out) const = 0;
+ virtual bool check(const std::vector<Event>& events, std::string* out) const {
+ for (const auto& e : events) {
+ if (!checkEvent(e, out)) {
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+class Vec3NormChecker : public SensorEventPerEventChecker {
+ public:
+ Vec3NormChecker(float min, float max) : mLowerLimit(min), mUpperLimit(max) {}
+ static Vec3NormChecker byNominal(float nominal, float allowedError) {
+ return Vec3NormChecker(nominal - allowedError, nominal + allowedError);
+ }
+
+ virtual bool checkEvent(const Event& event, std::string* out) const {
+ android::hardware::sensors::V1_0::Vec3 v = event.u.vec3;
+ float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
+ if (norm < mLowerLimit || norm > mUpperLimit) {
+ if (out != nullptr) {
+ std::ostringstream ss;
+ ss << "Event @ " << event.timestamp << " (" << v.x << ", " << v.y << ", " << v.z
+ << ")"
+ << " has norm " << norm << ", which is beyond range"
+ << " [" << mLowerLimit << ", " << mUpperLimit << "]";
+ *out = ss.str();
+ }
+ return false;
+ }
+ return true;
+ }
+
+ protected:
+ float mLowerLimit;
+ float mUpperLimit;
+};
+
+#endif // ANDROID_SENSOR_EVENTS_CHECKER_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
new file mode 100644
index 0000000..4a6f713
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
+#define ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
+
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+class SensorsHidlEnvironmentBase : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ using Event = ::android::hardware::sensors::V1_0::Event;
+ void HidlSetUp() override;
+ void HidlTearDown() override;
+
+ // Get and clear all events collected so far (like "cat" shell command).
+ // If output is nullptr, it clears all collected events.
+ void catEvents(std::vector<Event>* output);
+
+ // set sensor event collection status
+ void setCollection(bool enable);
+
+ protected:
+ SensorsHidlEnvironmentBase() {}
+
+ void addEvent(const Event& ev);
+
+ virtual void startPollingThread() = 0;
+ virtual bool resetHal() = 0;
+
+ bool collectionEnabled;
+ std::atomic_bool stopThread;
+ std::thread pollThread;
+ std::vector<Event> events;
+ std::mutex events_mutex;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase);
+};
+
+#endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
new file mode 100644
index 0000000..405dc28
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_TEST_BASE_H
+#define ANDROID_SENSORS_HIDL_TEST_BASE_H
+
+#include "sensors-vts-utils/SensorEventsChecker.h"
+#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <unordered_set>
+#include <vector>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::sensors::V1_0;
+
+class SensorsHidlTestBase : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual SensorsHidlEnvironmentBase* getEnvironment() = 0;
+ virtual void SetUp() override {}
+
+ virtual void TearDown() override {
+ // stop all sensors
+ for (auto s : mSensorHandles) {
+ activate(s, false);
+ }
+ mSensorHandles.clear();
+
+ // stop all direct report and channels
+ for (auto c : mDirectChannelHandles) {
+ // disable all reports
+ configDirectReport(-1, c, RateLevel::STOP, [](auto, auto) {});
+ unregisterDirectChannel(c);
+ }
+ mDirectChannelHandles.clear();
+ }
+
+ // implementation wrapper
+ virtual SensorInfo defaultSensorByType(SensorType type) = 0;
+ virtual Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) = 0;
+
+ virtual Return<Result> activate(int32_t sensorHandle, bool enabled) = 0;
+
+ virtual Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) = 0;
+
+ virtual Return<Result> flush(int32_t sensorHandle) = 0;
+ virtual Return<Result> injectSensorData(const Event& event) = 0;
+ virtual Return<void> registerDirectChannel(const SharedMemInfo& mem,
+ ISensors::registerDirectChannel_cb _hidl_cb) = 0;
+ virtual Return<Result> unregisterDirectChannel(int32_t channelHandle) = 0;
+ virtual Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle,
+ RateLevel rate,
+ ISensors::configDirectReport_cb _hidl_cb) = 0;
+
+ std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+ bool clearBeforeStart = true, bool changeCollection = true);
+
+ inline static SensorFlagBits extractReportMode(uint64_t flag) {
+ return (SensorFlagBits)(flag & ((uint64_t)SensorFlagBits::CONTINUOUS_MODE |
+ (uint64_t)SensorFlagBits::ON_CHANGE_MODE |
+ (uint64_t)SensorFlagBits::ONE_SHOT_MODE |
+ (uint64_t)SensorFlagBits::SPECIAL_REPORTING_MODE));
+ }
+
+ inline static bool isMetaSensorType(SensorType type) {
+ return (type == SensorType::META_DATA || type == SensorType::DYNAMIC_SENSOR_META ||
+ type == SensorType::ADDITIONAL_INFO);
+ }
+
+ inline static bool isValidType(SensorType type) { return (int32_t)type > 0; }
+
+ void testStreamingOperation(SensorType type, std::chrono::nanoseconds samplingPeriod,
+ std::chrono::seconds duration, const SensorEventsChecker& checker);
+ void testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow = true);
+ void testBatchingOperation(SensorType type);
+ void testDirectReportOperation(SensorType type, SharedMemType memType, RateLevel rate,
+ const SensorEventsChecker& checker);
+
+ static void assertTypeMatchStringType(SensorType type, const hidl_string& stringType);
+ static void assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode);
+ static void assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay,
+ SensorFlagBits reportMode);
+ static SensorFlagBits expectedReportModeForType(SensorType type);
+ static bool isDirectReportRateSupported(SensorInfo sensor, RateLevel rate);
+ static bool isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type);
+
+ protected:
+ // checkers
+ static const Vec3NormChecker sAccelNormChecker;
+ static const Vec3NormChecker sGyroNormChecker;
+
+ // all sensors and direct channnels used
+ std::unordered_set<int32_t> mSensorHandles;
+ std::unordered_set<int32_t> mDirectChannelHandles;
+};
+
+#endif // ANDROID_SENSORS_HIDL_TEST_BASE_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
new file mode 100644
index 0000000..055b8e7
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_TEST_SHARED_MEMORY_H
+#define ANDROID_SENSORS_TEST_SHARED_MEMORY_H
+
+#include "GrallocWrapper.h"
+
+#include <android-base/macros.h>
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <cutils/ashmem.h>
+
+class SensorsTestSharedMemory {
+ using SharedMemType = ::android::hardware::sensors::V1_0::SharedMemType;
+ using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
+ using Event = ::android::hardware::sensors::V1_0::Event;
+
+ public:
+ static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
+ SharedMemInfo getSharedMemInfo() const;
+ char* getBuffer() const;
+ std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
+ virtual ~SensorsTestSharedMemory();
+
+ private:
+ SensorsTestSharedMemory(SharedMemType type, size_t size);
+
+ SharedMemType mType;
+ native_handle_t* mNativeHandle;
+ size_t mSize;
+ char* mBuffer;
+ std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper;
+
+ DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
+};
+
+#endif // ANDROID_SENSORS_TEST_SHARED_MEMORY_H
diff --git a/tests/bar/1.0/default/Bar.cpp b/tests/bar/1.0/default/Bar.cpp
index 4614428..0a57b40 100644
--- a/tests/bar/1.0/default/Bar.cpp
+++ b/tests/bar/1.0/default/Bar.cpp
@@ -149,6 +149,10 @@
return mFoo->closeHandles();
}
+Return<void> Bar::repeatWithFmq(const IFoo::WithFmq& withFmq, repeatWithFmq_cb _hidl_cb) {
+ return mFoo->repeatWithFmq(withFmq, _hidl_cb);
+}
+
Return<void> Bar::echoNullInterface(const sp<IFooCallback> &cb, echoNullInterface_cb _hidl_cb) {
return mFoo->echoNullInterface(cb, _hidl_cb);
}
diff --git a/tests/bar/1.0/default/Bar.h b/tests/bar/1.0/default/Bar.h
index acb976f..4372266 100644
--- a/tests/bar/1.0/default/Bar.h
+++ b/tests/bar/1.0/default/Bar.h
@@ -56,6 +56,8 @@
virtual Return<void> createMyHandle(createMyHandle_cb _hidl_cb) override;
virtual Return<void> createHandles(uint32_t size, createHandles_cb _hidl_cb) override;
virtual Return<void> closeHandles() override;
+ virtual Return<void> repeatWithFmq(const IFoo::WithFmq& withFmq,
+ repeatWithFmq_cb _hidl_cb) override;
Return<void> haveAVectorOfInterfaces(
const hidl_vec<sp<ISimple> > &in,
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 8118d8b..91ed1f2 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -36,6 +36,17 @@
typedef SomeOtherEnum thisIsAnAlias;
typedef IBaz anIBazByAnyOtherName;
+ struct NastyNester {
+ struct NestersNasty {
+ struct NestersNastyNester {
+ IBaz baz;
+ vec<NestersNasty> nasties;
+ };
+ };
+
+ IBaz baz;
+ };
+
enum SomeEnum : SomeOtherEnum {
quux = 33,
goober = 192,
diff --git a/tests/foo/1.0/IFoo.hal b/tests/foo/1.0/IFoo.hal
index 4a930a2..4c54427 100644
--- a/tests/foo/1.0/IFoo.hal
+++ b/tests/foo/1.0/IFoo.hal
@@ -103,7 +103,6 @@
union U {
int8_t number;
int8_t[1][2] multidimArray;
- pointer p;
Fumble anotherStruct;
bitfield<BitField> bf;
} u;
@@ -122,6 +121,17 @@
bitfield<BitField> bf;
};
+ struct WithFmq {
+ struct ScatterGather {
+ fmq_sync<uint8_t> descSync;
+ } scatterGathered;
+
+ struct ContainsPointer {
+ fmq_sync<uint8_t> descSync;
+ interface foo;
+ } containsPointer;
+ };
+
enum Discriminator : uint8_t {
BOOL,
INT,
@@ -205,4 +215,6 @@
createMyHandle() generates (MyHandle h);
createHandles(uint32_t size) generates (vec<handle> handles);
closeHandles();
+
+ repeatWithFmq(WithFmq withFmq) generates (WithFmq withFmq);
};
diff --git a/tests/foo/1.0/default/Foo.cpp b/tests/foo/1.0/default/Foo.cpp
index a31ab9f..461568b 100644
--- a/tests/foo/1.0/default/Foo.cpp
+++ b/tests/foo/1.0/default/Foo.cpp
@@ -379,6 +379,11 @@
return Void();
}
+Return<void> Foo::repeatWithFmq(const IFoo::WithFmq& withFmq, repeatWithFmq_cb _hidl_cb) {
+ _hidl_cb(withFmq);
+ return Void();
+}
+
IFoo* HIDL_FETCH_IFoo(const char* /* name */) {
return new Foo();
}
diff --git a/tests/foo/1.0/default/Foo.h b/tests/foo/1.0/default/Foo.h
index 7dd672b..d73179a 100644
--- a/tests/foo/1.0/default/Foo.h
+++ b/tests/foo/1.0/default/Foo.h
@@ -53,6 +53,8 @@
virtual Return<void> createMyHandle(createMyHandle_cb _hidl_cb) override;
virtual Return<void> createHandles(uint32_t size, createHandles_cb _hidl_cb) override;
virtual Return<void> closeHandles() override;
+ virtual Return<void> repeatWithFmq(const IFoo::WithFmq& withFmq,
+ repeatWithFmq_cb _hidl_cb) override;
Return<void> haveAVectorOfInterfaces(
const hidl_vec<sp<ISimple> > &in,
@@ -63,6 +65,7 @@
haveAVectorOfGenericInterfaces_cb _hidl_cb) override;
Return<void> echoNullInterface(const sp<IFooCallback> &cb, echoNullInterface_cb _hidl_cb) override;
+
private:
std::vector<::native_handle_t *> mHandles;
};
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 2d9050d..61060b5 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -204,6 +204,19 @@
}
}
+ bool createRttController() {
+ bool success = false;
+ chip_->createRttController(
+ NULL, [&success](const WifiStatus& status,
+ const sp<IWifiRttController>& rtt) {
+ if (WifiStatusCode::SUCCESS == status.code) {
+ ASSERT_NE(rtt.get(), nullptr);
+ success = true;
+ }
+ });
+ return success;
+ }
+
public:
void SetUp() override {
chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
@@ -386,6 +399,29 @@
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
}
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowApToSta) {
+ findModeAndConfigureForIfaceType(IfaceType::AP);
+ const auto ap_iface_name = createIface(IfaceType::AP);
+ ASSERT_FALSE(ap_iface_name.empty());
+ ASSERT_FALSE(createRttController());
+
+ removeIface(IfaceType::AP, ap_iface_name);
+
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_TRUE(createRttController());
+}
+
////////// V2 + Aware Iface Combinations ////////////
// Mode 1 - STA + STA/AP
// - STA + P2P/NAN
@@ -540,6 +576,24 @@
ASSERT_NE(sta_iface_name, ap_iface_name);
}
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlow) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::AP).empty());
+ ASSERT_TRUE(createRttController());
+}
+
////////// V1 Iface Combinations when AP creation is disabled //////////
class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
public:
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index cf64e51..faf1862 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -930,6 +930,12 @@
std::pair<WifiStatus, sp<IWifiRttController>>
WifiChip::createRttControllerInternal(const sp<IWifiIface>& bound_iface) {
+ if (sta_ifaces_.size() == 0 &&
+ !canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
+ LOG(ERROR) << "createRttControllerInternal: Chip cannot support STAs "
+ "(and RTT by extension)";
+ return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+ }
sp<WifiRttController> rtt =
new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
rtt_controllers_.emplace_back(rtt);