Snap for 7080740 from 68a365af6dc8419d6fbd0dbb7a3d9e55dbf9b826 to mainline-networkstack-release
Change-Id: Id23f1a09c061aa4fecfd2761f693a5610b4a8de4
diff --git a/apps/test/chqts/src/busy_startup/busy_startup.cc b/apps/test/chqts/src/busy_startup/busy_startup.cc
index cfd8137..96623fe 100644
--- a/apps/test/chqts/src/busy_startup/busy_startup.cc
+++ b/apps/test/chqts/src/busy_startup/busy_startup.cc
@@ -146,7 +146,8 @@
checkTimerEvent(intData);
} else if (eventType == CHRE_EVENT_SENSOR_ACCELEROMETER_DATA) {
checkSensorEvent(eventData);
- } else if (eventType == CHRE_EVENT_SENSOR_SAMPLING_CHANGE) {
+ } else if (eventType == CHRE_EVENT_SENSOR_SAMPLING_CHANGE ||
+ eventType == CHRE_EVENT_SENSOR_ACCELEROMETER_BIAS_INFO) {
// This could have been generated when we configured the
// sensor. We just ignore it.
} else {
diff --git a/apps/test/chqts/src/general_test/basic_sensor_test_base.cc b/apps/test/chqts/src/general_test/basic_sensor_test_base.cc
index 4253866..9371a8f 100644
--- a/apps/test/chqts/src/general_test/basic_sensor_test_base.cc
+++ b/apps/test/chqts/src/general_test/basic_sensor_test_base.cc
@@ -163,9 +163,6 @@
void BasicSensorTestBase::startTest() {
mState = State::kPreConfigure;
if (!chreSensorFindDefault(getSensorType(), &mSensorHandle)) {
- if (isRequiredSensor()) {
- sendFatalFailureToHost("Sensor is required, but no default found.");
- }
sendStringToHost(MessageType::kSkipped,
"No default sensor found for optional sensor.");
return;
@@ -369,6 +366,8 @@
expectedSensorType = CHRE_SENSOR_TYPE_GYROSCOPE;
} else if (eventType == CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO) {
expectedSensorType = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
+ } else if (eventType == CHRE_EVENT_SENSOR_ACCELEROMETER_BIAS_INFO) {
+ expectedSensorType = CHRE_SENSOR_TYPE_ACCELEROMETER;
} else {
sendInternalFailureToHost("Illegal eventType in handleBiasEvent", &eType);
}
diff --git a/apps/test/chqts/src/general_test/basic_sensor_test_base.h b/apps/test/chqts/src/general_test/basic_sensor_test_base.h
index 1df3059..5e69aa7 100644
--- a/apps/test/chqts/src/general_test/basic_sensor_test_base.h
+++ b/apps/test/chqts/src/general_test/basic_sensor_test_base.h
@@ -49,16 +49,6 @@
virtual uint8_t getSensorType() const = 0;
/**
- * Abstract method indicating if this sensor is required for a valid
- * CHRE implementation.
- *
- * A CHRE isn't useful without certain sensors available.
- *
- * @returns true if this is sensor is required; false otherwise.
- */
- virtual bool isRequiredSensor() const = 0;
-
- /**
* Abstract method indicating if this is an on-change sensor.
*
* @returns true if this sensor is on-change; false otherwise.
diff --git a/apps/test/chqts/src/general_test/basic_sensor_tests.h b/apps/test/chqts/src/general_test/basic_sensor_tests.h
index 7638eff..8fd8257 100644
--- a/apps/test/chqts/src/general_test/basic_sensor_tests.h
+++ b/apps/test/chqts/src/general_test/basic_sensor_tests.h
@@ -31,9 +31,6 @@
uint8_t getSensorType() const override {
return CHRE_SENSOR_TYPE_ACCELEROMETER;
}
- bool isRequiredSensor() const override {
- return true;
- }
bool isOnChangeSensor() const override {
return false;
}
@@ -51,9 +48,6 @@
uint8_t getSensorType() const override {
return CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT;
}
- bool isRequiredSensor() const override {
- return true;
- }
bool isOnChangeSensor() const override {
return false;
}
@@ -71,9 +65,6 @@
uint8_t getSensorType() const override {
return CHRE_SENSOR_TYPE_STATIONARY_DETECT;
}
- bool isRequiredSensor() const override {
- return true;
- }
bool isOnChangeSensor() const override {
return false;
}
@@ -91,9 +82,6 @@
uint8_t getSensorType() const override {
return CHRE_SENSOR_TYPE_GYROSCOPE;
}
- bool isRequiredSensor() const override {
- return true;
- }
bool isOnChangeSensor() const override {
return false;
}
@@ -111,9 +99,6 @@
uint8_t getSensorType() const override {
return CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
}
- bool isRequiredSensor() const override {
- return false;
- }
bool isOnChangeSensor() const override {
return false;
}
@@ -131,9 +116,6 @@
uint8_t getSensorType() const override {
return CHRE_SENSOR_TYPE_PRESSURE;
}
- bool isRequiredSensor() const override {
- return false;
- }
bool isOnChangeSensor() const override {
return false;
}
@@ -151,9 +133,6 @@
uint8_t getSensorType() const override {
return CHRE_SENSOR_TYPE_LIGHT;
}
- bool isRequiredSensor() const override {
- return false;
- }
bool isOnChangeSensor() const override {
return true;
}
@@ -171,9 +150,6 @@
uint8_t getSensorType() const override {
return CHRE_SENSOR_TYPE_PROXIMITY;
}
- bool isRequiredSensor() const override {
- return false;
- }
bool isOnChangeSensor() const override {
return true;
}
diff --git a/apps/test/common/chre_cross_validator_sensor/inc/chre_cross_validator_sensor_manager.h b/apps/test/common/chre_cross_validator_sensor/inc/chre_cross_validator_sensor_manager.h
index 6b2229c..2b87162 100644
--- a/apps/test/common/chre_cross_validator_sensor/inc/chre_cross_validator_sensor_manager.h
+++ b/apps/test/common/chre_cross_validator_sensor/inc/chre_cross_validator_sensor_manager.h
@@ -207,9 +207,20 @@
/**
* Handle a start message from CHRE with the given data from host.
*
+ * @param hostEndpoint The host endpoint the data was sent from.
* @param hostData The data from host that has a start message.
*/
- void handleStartMessage(const chreMessageFromHostData *hostData);
+ void handleStartMessage(uint16_t hostEndpoint,
+ const chreMessageFromHostData *hostData);
+
+ /**
+ * Handle an info message from CHRE with the given data from host.
+ *
+ * @param hostEndpoint The host endpoint the data was sent from.
+ * @param hostData The data from host that has a start message.
+ */
+ void handleInfoMessage(uint16_t hostEndpoint,
+ const chreMessageFromHostData *hostData);
/**
* Handle a message from the host.
@@ -276,11 +287,33 @@
void handleProximityData(const chreSensorByteData *proximityDataFromChre);
/**
- * Encode and send data to be validated to host.
+ * Send data to be validated to the host.
*
- * @param data The data to encode and send.
+ * @param data The data to send.
*/
- void encodeAndSendDataToHost(const chre_cross_validation_sensor_Data &data);
+ void sendDataToHost(const chre_cross_validation_sensor_Data &data);
+
+ /**
+ * Encode and send the info response to the host.
+ *
+ * @param hostEndpoint The endpoint to send the response to.
+ * @param infoResponse The info response to be encoded and sent.
+ */
+ void sendInfoResponse(
+ uint16_t hostEndpoint,
+ const chre_cross_validation_sensor_SensorInfoResponse &infoResponse);
+
+ /**
+ * Sends the provided message to the host.
+ *
+ * @param hostEndpoint The endpoint to send the message to.
+ * @param messageType The type of message being sent to the host.
+ * @param fields The fields of the provided struct that should be encoded.
+ * @param srcStruct The struct that should be encoded prior to sending to the
+ * host.
+ */
+ void sendMessageToHost(uint16_t hostEndpoint, uint16_t messageType,
+ const pb_field_t fields[], const void *srcStruct);
/**
* Determine if nanoapp is ready to process new sensor data.
diff --git a/apps/test/common/chre_cross_validator_sensor/src/chre_cross_validator_sensor_manager.cc b/apps/test/common/chre_cross_validator_sensor/src/chre_cross_validator_sensor_manager.cc
index 4d8be7a..02fa263 100644
--- a/apps/test/common/chre_cross_validator_sensor/src/chre_cross_validator_sensor_manager.cc
+++ b/apps/test/common/chre_cross_validator_sensor/src/chre_cross_validator_sensor_manager.cc
@@ -300,14 +300,9 @@
return header.readingCount > 0 && isTimestampValid;
}
-void Manager::handleStartMessage(const chreMessageFromHostData *hostData) {
+void Manager::handleStartMessage(uint16_t hostEndpoint,
+ const chreMessageFromHostData *hostData) {
bool success = true;
- uint16_t hostEndpoint;
- if (hostData->hostEndpoint != CHRE_HOST_ENDPOINT_UNSPECIFIED) {
- hostEndpoint = hostData->hostEndpoint;
- } else {
- hostEndpoint = CHRE_HOST_ENDPOINT_BROADCAST;
- }
// Default values for everything but hostEndpoint param
mCrossValidatorState = CrossValidatorState(CrossValidatorType::SENSOR, 0, 0,
0, hostEndpoint, false);
@@ -335,14 +330,48 @@
}
}
+void Manager::handleInfoMessage(uint16_t hostEndpoint,
+ const chreMessageFromHostData *hostData) {
+ chre_cross_validation_sensor_SensorInfoResponse infoResponse =
+ chre_cross_validation_sensor_SensorInfoResponse_init_default;
+ pb_istream_t istream = pb_istream_from_buffer(
+ static_cast<const pb_byte_t *>(hostData->message), hostData->messageSize);
+ chre_cross_validation_sensor_SensorInfoCommand infoCommand =
+ chre_cross_validation_sensor_SensorInfoCommand_init_default;
+ if (!pb_decode(&istream,
+ chre_cross_validation_sensor_SensorInfoCommand_fields,
+ &infoCommand)) {
+ LOGE("Could not decode info command");
+ } else {
+ uint32_t handle;
+ infoResponse.has_chreSensorType = true;
+ infoResponse.chreSensorType = infoCommand.chreSensorType;
+ infoResponse.has_isAvailable = true;
+ infoResponse.isAvailable =
+ chreSensorFindDefault(infoResponse.chreSensorType, &handle);
+ }
+
+ sendInfoResponse(hostEndpoint, infoResponse);
+}
+
void Manager::handleMessageFromHost(uint32_t senderInstanceId,
const chreMessageFromHostData *hostData) {
if (senderInstanceId != CHRE_INSTANCE_ID) {
LOGE("Incorrect sender instance id: %" PRIu32, senderInstanceId);
} else {
+ uint16_t hostEndpoint;
+ if (hostData->hostEndpoint != CHRE_HOST_ENDPOINT_UNSPECIFIED) {
+ hostEndpoint = hostData->hostEndpoint;
+ } else {
+ hostEndpoint = CHRE_HOST_ENDPOINT_BROADCAST;
+ }
+
switch (hostData->messageType) {
case chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_START:
- handleStartMessage(hostData);
+ handleStartMessage(hostEndpoint, hostData);
+ break;
+ case chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_INFO:
+ handleInfoMessage(hostEndpoint, hostData);
break;
default:
LOGE("Unknown message type %" PRIu32 " for host message",
@@ -416,7 +445,7 @@
if (processSensorData(threeAxisDataFromChre->header, sensorType)) {
chre_cross_validation_sensor_Data newData =
makeSensorThreeAxisData(threeAxisDataFromChre, sensorType);
- encodeAndSendDataToHost(newData);
+ sendDataToHost(newData);
}
}
@@ -425,7 +454,7 @@
if (processSensorData(floatDataFromChre->header, sensorType)) {
chre_cross_validation_sensor_Data newData =
makeSensorFloatData(floatDataFromChre, sensorType);
- encodeAndSendDataToHost(newData);
+ sendDataToHost(newData);
}
}
@@ -435,30 +464,43 @@
CHRE_SENSOR_TYPE_PROXIMITY)) {
chre_cross_validation_sensor_Data newData =
makeSensorProximityData(proximityDataFromChre);
- encodeAndSendDataToHost(newData);
+ sendDataToHost(newData);
}
}
-void Manager::encodeAndSendDataToHost(
- const chre_cross_validation_sensor_Data &data) {
+void Manager::sendDataToHost(const chre_cross_validation_sensor_Data &data) {
+ sendMessageToHost(
+ mCrossValidatorState->hostEndpoint,
+ chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_DATA,
+ chre_cross_validation_sensor_Data_fields, &data);
+}
+
+void Manager::sendInfoResponse(
+ uint16_t hostEndpoint,
+ const chre_cross_validation_sensor_SensorInfoResponse &infoResponse) {
+ sendMessageToHost(
+ hostEndpoint,
+ chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_INFO_RESPONSE,
+ chre_cross_validation_sensor_SensorInfoResponse_fields, &infoResponse);
+}
+
+void Manager::sendMessageToHost(uint16_t hostEndpoint, uint16_t messageType,
+ const pb_field_t fields[],
+ const void *srcStruct) {
size_t encodedSize;
- if (!pb_get_encoded_size(&encodedSize,
- chre_cross_validation_sensor_Data_fields, &data)) {
- LOGE("Could not get encoded size of data proto message");
+ if (!pb_get_encoded_size(&encodedSize, fields, srcStruct)) {
+ LOGE("Could not get encoded size of proto message");
} else {
pb_byte_t *buffer = static_cast<pb_byte_t *>(chreHeapAlloc(encodedSize));
if (buffer == nullptr) {
LOG_OOM();
} else {
pb_ostream_t ostream = pb_ostream_from_buffer(buffer, encodedSize);
- if (!pb_encode(&ostream, chre_cross_validation_sensor_Data_fields,
- &data)) {
- LOGE("Could not encode data proto message");
- } else if (
- !chreSendMessageToHostEndpoint(
- static_cast<void *>(buffer), encodedSize,
- chre_cross_validation_sensor_MessageType_CHRE_CROSS_VALIDATION_DATA,
- mCrossValidatorState->hostEndpoint, heapFreeMessageCallback)) {
+ if (!pb_encode(&ostream, fields, srcStruct)) {
+ LOGE("Could not encode proto message");
+ } else if (!chreSendMessageToHostEndpoint(
+ static_cast<void *>(buffer), encodedSize, messageType,
+ hostEndpoint, heapFreeMessageCallback)) {
LOGE("Could not send message to host");
}
}
diff --git a/apps/test/common/chre_cross_validator_wifi/inc/chre_cross_validator_wifi_manager.h b/apps/test/common/chre_cross_validator_wifi/inc/chre_cross_validator_wifi_manager.h
index e1d5c27..0ca0a7e 100644
--- a/apps/test/common/chre_cross_validator_wifi/inc/chre_cross_validator_wifi_manager.h
+++ b/apps/test/common/chre_cross_validator_wifi/inc/chre_cross_validator_wifi_manager.h
@@ -107,13 +107,22 @@
bool success, const char *errMessage = nullptr);
/**
+ * @param capabilitiesFromChre The number with flags that represent the
+ * different wifi capabilities.
+ * @return The wifi capabilities proto message for the host.
+ */
+ chre_cross_validation_wifi_WifiCapabilities makeWifiCapabilitiesMessage(
+ uint32_t capabilitiesFromChre);
+
+ /**
* Encode the proto message and send to host.
*
* @param message The proto message struct pointer.
- * @fields The fields descriptor of the proto message to encode.
+ * @param fields The fields descriptor of the proto message to encode.
+ * @param messageType The message type of the message.
*/
- void encodeAndSendMessageToHost(const void *message,
- const pb_field_t *fields);
+ void encodeAndSendMessageToHost(const void *message, const pb_field_t *fields,
+ uint32_t messageType);
/**
* Handle a wifi scan result data message sent from AP.
*
diff --git a/apps/test/common/chre_cross_validator_wifi/src/chre_cross_validator_wifi_manager.cc b/apps/test/common/chre_cross_validator_wifi/src/chre_cross_validator_wifi_manager.cc
index a57768d..c23efed 100644
--- a/apps/test/common/chre_cross_validator_wifi/src/chre_cross_validator_wifi_manager.cc
+++ b/apps/test/common/chre_cross_validator_wifi/src/chre_cross_validator_wifi_manager.cc
@@ -19,6 +19,7 @@
#include <cinttypes>
#include <cstring>
+#include "chre/util/nanoapp/assert.h"
#include "chre/util/nanoapp/callbacks.h"
#include "chre/util/nanoapp/log.h"
#include "chre_cross_validation_wifi.nanopb.h"
@@ -89,24 +90,35 @@
void Manager::handleStepStartMessage(
chre_cross_validation_wifi_StepStartCommand stepStartCommand) {
- chre_test_common_TestResult testResult;
switch (stepStartCommand.step) {
case chre_cross_validation_wifi_Step_INIT:
- testResult = makeTestResultProtoMessage(
- false, "Received StepStartCommand for INIT step");
+ LOGE("Received StepStartCommand for INIT step");
+ CHRE_ASSERT(false);
break;
- case chre_cross_validation_wifi_Step_SETUP:
+ case chre_cross_validation_wifi_Step_CAPABILITIES: {
+ chre_cross_validation_wifi_WifiCapabilities wifiCapabilities =
+ makeWifiCapabilitiesMessage(chreWifiGetCapabilities());
+ encodeAndSendMessageToHost(
+ static_cast<void *>(&wifiCapabilities),
+ chre_cross_validation_wifi_WifiCapabilities_fields,
+ chre_cross_validation_wifi_MessageType_WIFI_CAPABILITIES);
+ break;
+ }
+ case chre_cross_validation_wifi_Step_SETUP: {
if (!chreWifiConfigureScanMonitorAsync(true /* enable */,
&kScanMonitoringCookie)) {
LOGE("chreWifiConfigureScanMonitorAsync() failed");
- testResult =
+ chre_test_common_TestResult testResult =
makeTestResultProtoMessage(false, "setupWifiScanMonitoring failed");
- encodeAndSendMessageToHost(static_cast<void *>(&testResult),
- chre_test_common_TestResult_fields);
+ encodeAndSendMessageToHost(
+ static_cast<void *>(&testResult),
+ chre_test_common_TestResult_fields,
+ chre_cross_validation_wifi_MessageType_STEP_RESULT);
} else {
LOGD("chreWifiConfigureScanMonitorAsync() succeeded");
}
break;
+ }
case chre_cross_validation_wifi_Step_VALIDATE:
LOGE("start message received in VALIDATE phase");
break;
@@ -174,8 +186,10 @@
}
}
}
- encodeAndSendMessageToHost(static_cast<const void *>(&testResult),
- chre_test_common_TestResult_fields);
+ encodeAndSendMessageToHost(
+ static_cast<const void *>(&testResult),
+ chre_test_common_TestResult_fields,
+ chre_cross_validation_wifi_MessageType_STEP_RESULT);
chreHeapFree(errMsg);
}
}
@@ -208,8 +222,17 @@
return testResult;
}
+chre_cross_validation_wifi_WifiCapabilities
+Manager::makeWifiCapabilitiesMessage(uint32_t capabilitiesFromChre) {
+ chre_cross_validation_wifi_WifiCapabilities capabilities;
+ capabilities.has_wifiCapabilities = true;
+ capabilities.wifiCapabilities = capabilitiesFromChre;
+ return capabilities;
+}
+
void Manager::encodeAndSendMessageToHost(const void *message,
- const pb_field_t *fields) {
+ const pb_field_t *fields,
+ uint32_t messageType) {
size_t encodedSize;
if (!pb_get_encoded_size(&encodedSize, fields, message)) {
LOGE("Could not get encoded size of test result message");
@@ -222,8 +245,7 @@
if (!pb_encode(&ostream, fields, message)) {
LOGE("Could not encode data proto message");
} else if (!chreSendMessageToHostEndpoint(
- static_cast<void *>(buffer), encodedSize,
- chre_cross_validation_wifi_MessageType_STEP_RESULT,
+ static_cast<void *>(buffer), encodedSize, messageType,
mCrossValidatorState.hostEndpoint,
heapFreeMessageCallback)) {
LOGE("Could not send message to host");
@@ -254,8 +276,9 @@
testResult = makeTestResultProtoMessage(
false, "Unknown chre async result type received");
}
- encodeAndSendMessageToHost(static_cast<void *>(&testResult),
- chre_test_common_TestResult_fields);
+ encodeAndSendMessageToHost(
+ static_cast<void *>(&testResult), chre_test_common_TestResult_fields,
+ chre_cross_validation_wifi_MessageType_STEP_RESULT);
}
} // namespace cross_validator_wifi
diff --git a/apps/test/common/proto/chre_cross_validation_sensor.proto b/apps/test/common/proto/chre_cross_validation_sensor.proto
index a7db174..94b9cde 100644
--- a/apps/test/common/proto/chre_cross_validation_sensor.proto
+++ b/apps/test/common/proto/chre_cross_validation_sensor.proto
@@ -18,6 +18,14 @@
// was received from a CHRE API.
// Payload must be Data message
CHRE_CROSS_VALIDATION_DATA = 2;
+
+ // H2C: Host asking nanoapp for information about a given sensor.
+ // Payload must be SensorInfoCommand message.
+ CHRE_CROSS_VALIDATION_INFO = 3;
+
+ // C2H: Response to a information request for a sensor.
+ // Payload must be a SensorInfoResponse message.
+ CHRE_CROSS_VALIDATION_INFO_RESPONSE = 4;
}
message StartCommand {
@@ -37,6 +45,21 @@
optional bool isContinuous = 4;
}
+/*
+ * Asks for the nanoapp to provide stats about the provided CHRE sensor type.
+ */
+message SensorInfoCommand {
+ optional uint32 chreSensorType = 1;
+}
+
+/*
+ * Response to a SensorInfoCommand containing data about the requested sensor.
+ */
+message SensorInfoResponse {
+ optional uint32 chreSensorType = 1;
+ optional bool isAvailable = 2;
+}
+
message Data {
oneof data {
SensorData sensorData = 1;
diff --git a/apps/test/common/proto/chre_cross_validation_wifi.proto b/apps/test/common/proto/chre_cross_validation_wifi.proto
index 8a400f4..d2fe7e0 100644
--- a/apps/test/common/proto/chre_cross_validation_wifi.proto
+++ b/apps/test/common/proto/chre_cross_validation_wifi.proto
@@ -22,6 +22,10 @@
// H2C: Host passing down wifi scan result data to CHRE to validate.
// There may be multiple messages with this type sent.
SCAN_RESULT = 3;
+
+ // C2H: Nanoapp informing host about the wifi capabilities it has.
+ // The payload must be a WifiCapabilities message.
+ WIFI_CAPABILITIES = 4;
}
enum Step {
@@ -31,6 +35,8 @@
SETUP = 1;
// The validate step where the data is gathered and compared.
VALIDATE = 2;
+ // The step where the wifi capabilities are gathered from the nanoapp.
+ CAPABILITIES = 3;
}
message StepStartCommand {
@@ -54,3 +60,11 @@
// [0 - totalNumResults)
optional uint32 resultIndex = 4;
}
+
+/*
+ * The wifi capabilities listed in
+ * //system/chre/chre_api/include/chre_api/chre/wifi.h
+ */
+message WifiCapabilities {
+ optional uint32 wifiCapabilities = 1;
+}
diff --git a/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorSensor.java b/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorSensor.java
index eb35dda..4f8db72 100644
--- a/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorSensor.java
+++ b/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorSensor.java
@@ -37,10 +37,11 @@
import org.junit.Assert;
import org.junit.Assume;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class ChreCrossValidatorSensor
@@ -65,11 +66,10 @@
private static final long AWAIT_DATA_TIMEOUT_CONTINUOUS_IN_MS = 5000;
private static final long AWAIT_DATA_TIMEOUT_ON_CHANGE_ONE_SHOT_IN_MS = 1000;
+ private static final long INFO_RESPONSE_TIMEOUT_MS = 1000;
private static final long DEFAULT_SAMPLING_INTERVAL_IN_MS = 20;
- // TODO(b/146052784): May need to account for differences in sampling rate and latency from
- // AP side vs CHRE side
private static final long SAMPLING_LATENCY_IN_MS = 0;
private static final long MAX_TIMESTAMP_DIFF_NS = 10000000L;
@@ -86,6 +86,7 @@
private Sensor mSensor;
private long mSamplingIntervalInMs;
+ private boolean mChreSensorFound;
private CrossValidatorSensorConfig mSensorConfig;
@@ -131,6 +132,7 @@
@Override
public void validate() throws AssertionError {
+ verifyChreSensorIsPresent();
collectDataFromAp();
collectDataFromChre();
waitForDataSampling();
@@ -156,8 +158,59 @@
mNappBinary.getNanoAppId(), messageType, startCommand.toByteArray());
}
+ /**
+ * @return The nanoapp message used to retrieve info of a given CHRE sensor.
+ */
+ private NanoAppMessage makeInfoCommandMessage() {
+ int messageType = ChreCrossValidationSensor.MessageType.CHRE_CROSS_VALIDATION_INFO_VALUE;
+ ChreCrossValidationSensor.SensorInfoCommand infoCommand =
+ ChreCrossValidationSensor.SensorInfoCommand.newBuilder()
+ .setChreSensorType(getChreSensorType())
+ .build();
+ return NanoAppMessage.createMessageToNanoApp(
+ mNappBinary.getNanoAppId(), messageType, infoCommand.toByteArray());
+ }
+
@Override
protected void parseDataFromNanoAppMessage(NanoAppMessage message) {
+ if (message.getMessageType()
+ == ChreCrossValidationSensor.MessageType
+ .CHRE_CROSS_VALIDATION_INFO_RESPONSE_VALUE) {
+ parseInfoResponseFromNanoappMessage(message);
+ } else if (message.getMessageType()
+ == ChreCrossValidationSensor.MessageType.CHRE_CROSS_VALIDATION_DATA_VALUE) {
+ parseSensorDataFromNanoappMessage(message);
+ } else {
+ Assert.fail("Received invalid message type from nanoapp " + message.getMessageType());
+ }
+ }
+
+ private void parseInfoResponseFromNanoappMessage(NanoAppMessage message) {
+ ChreCrossValidationSensor.SensorInfoResponse infoProto;
+ try {
+ infoProto = ChreCrossValidationSensor.SensorInfoResponse.parseFrom(
+ message.getMessageBody());
+ } catch (InvalidProtocolBufferException e) {
+ setErrorStr("Error parsing protobuf: " + e);
+ return;
+ }
+ if (!infoProto.hasChreSensorType() || !infoProto.hasIsAvailable()) {
+ setErrorStr("Info response message isn't completely filled in");
+ return;
+ }
+
+ int apSensorType = chreToApSensorType(infoProto.getChreSensorType());
+ if (!isSensorTypeCurrent(apSensorType)) {
+ setErrorStr(String.format("Incorrect sensor type %d when expecting %d",
+ apSensorType, mSensor.getType()));
+ return;
+ }
+
+ mChreSensorFound = infoProto.getIsAvailable();
+ mAwaitDataLatch.countDown();
+ }
+
+ private void parseSensorDataFromNanoappMessage(NanoAppMessage message) {
final String kParseDataErrorPrefix = "While parsing data from nanoapp: ";
ChreCrossValidationSensor.Data dataProto;
try {
@@ -201,8 +254,6 @@
Assert.assertTrue("Did not find any AP datapoints", mApDatapointsArray.length > 0);
alignApAndChreDatapoints();
// AP and CHRE datapoints will be same size
- // TODO(b/146052784): Ensure that CHRE data is the same sampling rate as AP data for
- // comparison
for (int i = 0; i < mApDatapointsArray.length; i++) {
assertSensorDatapointsSimilar(
(ApSensorDatapoint) mApDatapointsArray[i],
@@ -309,10 +360,14 @@
/**
* Start collecting data from CHRE
*/
- private void collectDataFromChre() throws AssertionError {
+ private void collectDataFromChre() {
// The info in the start message will inform the nanoapp of which type of
// data to collect (accel, gyro, gnss, wifi, etc).
- int result = mContextHubClient.sendMessageToNanoApp(makeStartNanoAppMessage());
+ sendMessageToNanoApp(makeStartNanoAppMessage());
+ }
+
+ private void sendMessageToNanoApp(NanoAppMessage message) {
+ int result = mContextHubClient.sendMessageToNanoApp(message);
if (result != ContextHubTransaction.RESULT_SUCCESS) {
Assert.fail("Collect data from CHRE failed with result "
+ contextHubTransactionResultToString(result)
@@ -341,35 +396,35 @@
}
/*
- * Align the AP and CHRE datapoints by finding the first pair that are similar comparing
- * linearly from there. Also truncate the end if one list has more datapoints than the other
- * after this. This is needed because AP and CHRE can start sending data and varying times to
- * this validator and can also stop sending at various times.
+ * Align the AP and CHRE datapoints by finding all the timestamps that match up and discarding
+ * the rest of the datapoints.
*/
private void alignApAndChreDatapoints() throws AssertionError {
- int matchAp = 0, matchChre = 0;
- int shorterDpLength = Math.min(mApDatapointsArray.length, mChreDatapointsArray.length);
- if (mApDatapointsArray[0].timestamp < mChreDatapointsArray[0].timestamp) {
- matchChre = 0;
- matchAp = indexOfFirstClosestDatapoint((SensorDatapoint[]) mApDatapointsArray,
- mChreDatapointsArray[0]);
- } else {
- matchAp = 0;
- matchChre = indexOfFirstClosestDatapoint((SensorDatapoint[]) mChreDatapointsArray,
- mApDatapointsArray[0]);
+ ArrayList<ApSensorDatapoint> newApSensorDatapoints = new ArrayList<ApSensorDatapoint>();
+ ArrayList<ChreSensorDatapoint> newChreSensorDatapoints =
+ new ArrayList<ChreSensorDatapoint>();
+ int apI = 0;
+ int chreI = 0;
+ while (apI < mApDatapointsArray.length && chreI < mChreDatapointsArray.length) {
+ ApSensorDatapoint apDp = mApDatapointsArray[apI];
+ ChreSensorDatapoint chreDp = mChreDatapointsArray[chreI];
+ if (datapointTimestampsAreSimilar(apDp, chreDp)) {
+ newApSensorDatapoints.add(apDp);
+ newChreSensorDatapoints.add(chreDp);
+ apI++;
+ chreI++;
+ } else if (apDp.timestamp < chreDp.timestamp) {
+ apI++;
+ } else {
+ chreI++;
+ }
}
+ // TODO(b/175795665): Assert that an acceptable amount of datapoints pass the alignment
+ // phase.
Assert.assertTrue("Did not find matching timestamps to align AP and CHRE datapoints.",
- (matchAp != -1 && matchChre != -1));
- // Remove extraneous datapoints before matching datapoints
- int apStartI = matchAp;
- int chreStartI = matchChre;
- int newApLength = mApDatapointsArray.length - apStartI;
- int newChreLength = mChreDatapointsArray.length - chreStartI;
- int minLength = Math.min(newApLength, newChreLength);
- int chreEndI = chreStartI + minLength;
- int apEndI = apStartI + minLength;
- mApDatapointsArray = Arrays.copyOfRange(mApDatapointsArray, apStartI, apEndI);
- mChreDatapointsArray = Arrays.copyOfRange(mChreDatapointsArray, chreStartI, chreEndI);
+ !(newApSensorDatapoints.isEmpty() || newChreSensorDatapoints.isEmpty()));
+ mApDatapointsArray = newApSensorDatapoints.toArray(new ApSensorDatapoint[0]);
+ mChreDatapointsArray = newChreSensorDatapoints.toArray(new ChreSensorDatapoint[0]);
}
/**
@@ -402,10 +457,6 @@
String.format("AP and CHRE three axis datapoint values differ on index %d", index)
+ "\nAP data -> " + apDp + "\nCHRE data -> "
+ chreDp;
- String timestampsAssertMsg =
- String.format("AP and CHRE three axis timestamp values differ on index %d", index)
- + "\nAP data -> " + apDp + "\nCHRE data -> "
- + chreDp;
// TODO(b/146052784): Log full list of datapoints to file on disk on assertion failure
// so that there is more insight into the problem then just logging the one pair of
@@ -413,23 +464,6 @@
Assert.assertTrue(datapointsAssertMsg,
datapointValuesAreSimilar(
apDp, chreDp, mSensorConfig.errorMargin));
- Assert.assertTrue(timestampsAssertMsg,
- datapointTimestampsAreSimilar(apDp, chreDp));
- }
-
- /**
- * @param datapoints Array of dataoints to compare timestamps to laterDp
- * @param laterDp SensorDatapoint whose timestamp will be compared to the datapoints in array
- * to find the first pair that match.
- */
- private int indexOfFirstClosestDatapoint(SensorDatapoint[] sensorDatapoints,
- SensorDatapoint laterDp) {
- for (int i = 0; i < sensorDatapoints.length; i++) {
- if (datapointTimestampsAreSimilar(sensorDatapoints[i], laterDp)) {
- return i;
- }
- }
- return -1;
}
/**
@@ -448,6 +482,38 @@
return AP_TO_CHRE_SENSOR_TYPE.get(mSensor.getType());
}
+ /**
+ * Verify the CHRE sensor being evaluated is present on this device.
+ */
+ private void verifyChreSensorIsPresent() {
+ mCollectingData.set(true);
+ sendMessageToNanoApp(makeInfoCommandMessage());
+ waitForInfoResponse();
+ mCollectingData.set(false);
+ // All CHRE sensors are optional so skip this test if the required sensor isn't found.
+ Assume.assumeTrue(mChreSensorFound);
+ }
+
+ private void waitForInfoResponse() {
+ boolean success = false;
+ try {
+ success = mAwaitDataLatch.await(INFO_RESPONSE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Assert.fail("await data latch interrupted");
+ }
+
+ if (!success) {
+ Assert.fail("Timed out waiting for sensor info response");
+ }
+
+ if (mErrorStr.get() != null) {
+ Assert.fail(mErrorStr.get());
+ }
+
+ // Reset latch for use in waiting for sensor data.
+ mAwaitDataLatch = new CountDownLatch(1);
+ }
+
private boolean sensorIsContinuous() {
return mSensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS;
}
diff --git a/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorWifi.java b/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorWifi.java
index bd08e81..a938288 100644
--- a/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorWifi.java
+++ b/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorWifi.java
@@ -38,6 +38,7 @@
import com.google.protobuf.InvalidProtocolBufferException;
import org.junit.Assert;
+import org.junit.Assume;
import java.math.BigInteger;
import java.util.List;
@@ -52,6 +53,13 @@
private static final long NANO_APP_ID = 0x476f6f6754000005L;
+ /**
+ * Wifi capabilities flags listed in
+ * //system/chre/chre_api/include/chre_api/chre/wifi.h
+ */
+ private static final int WIFI_CAPABILITIES_SCAN_MONITORING = 1;
+ private static final int WIFI_CAPABILITIES_ON_DEMAND_SCAN = 2;
+
AtomicReference<Step> mStep = new AtomicReference<Step>(Step.INIT);
AtomicBoolean mDidReceiveNanoAppMessage = new AtomicBoolean(false);
@@ -61,6 +69,9 @@
private WifiManager mWifiManager;
private BroadcastReceiver mWifiScanReceiver;
+ private AtomicReference<ChreCrossValidationWifi.WifiCapabilities> mWifiCapabilities =
+ new AtomicReference<ChreCrossValidationWifi.WifiCapabilities>(null);
+
private AtomicBoolean mWifiScanResultsCompareFinalResult = new AtomicBoolean(false);
private AtomicReference<String> mWifiScanResultsCompareFinalErrorMessage =
new AtomicReference<String>(null);
@@ -90,17 +101,27 @@
}
@Override public void validate() throws AssertionError {
- mStep.set(Step.SETUP);
- sendStepStartMessage(Step.SETUP);
- waitForStepResult();
+ mCollectingData.set(true);
+ sendStepStartMessage(Step.CAPABILITIES);
+ waitForMessageFromNanoapp();
+ mCollectingData.set(false);
+ Assume.assumeTrue("Chre wifi is not enabled",
+ chreWifiHasCapabilities(mWifiCapabilities.get()));
+ mCollectingData.set(true);
+ sendStepStartMessage(Step.SETUP);
+ waitForMessageFromNanoapp();
+ mCollectingData.set(false);
+
+ mCollectingData.set(true);
sendStepStartMessage(Step.VALIDATE);
Assert.assertTrue("Wifi manager start scan failed", mWifiManager.startScan());
waitForApScanResults();
sendWifiScanResultsToChre();
- waitForStepResult();
+ waitForMessageFromNanoapp();
+ mCollectingData.set(false);
}
@@ -108,7 +129,7 @@
* Send step start message to nanoapp.
*/
private void sendStepStartMessage(Step step) {
- mStep.set(Step.VALIDATE);
+ mStep.set(step);
sendMessageToNanoApp(makeStepStartMessage(step));
}
@@ -138,16 +159,14 @@
}
/**
- * Wait for setup message from CHRE or CHRE_ERROR
+ * Wait for a messaage from the nanoapp.
*/
- private void waitForStepResult() {
- mCollectingData.set(true);
+ private void waitForMessageFromNanoapp() {
try {
mAwaitDataLatch.await(AWAIT_STEP_RESULT_MESSAGE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Assert.fail("Interrupted while awaiting " + getCurrentStepName() + " step");
}
- mCollectingData.set(false);
mAwaitDataLatch = new CountDownLatch(1);
Assert.assertTrue("Timed out while waiting for step result in " + getCurrentStepName()
+ " step", mDidReceiveNanoAppMessage.get());
@@ -157,6 +176,15 @@
}
}
+ /**
+ * @param capabilities The wifi capabilities message from CHRE.
+ * @return true if CHRE wifi has the necessary capabilities to run the test.
+ */
+ private boolean chreWifiHasCapabilities(ChreCrossValidationWifi.WifiCapabilities capabilities) {
+ return (capabilities.getWifiCapabilities() & WIFI_CAPABILITIES_SCAN_MONITORING) != 0
+ && (capabilities.getWifiCapabilities() & WIFI_CAPABILITIES_ON_DEMAND_SCAN) != 0;
+ }
+
private void waitForApScanResults() {
try {
mAwaitApWifiSetupScan.await(AWAIT_WIFI_SCAN_RESULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
@@ -186,34 +214,48 @@
return message;
}
-
@Override
protected void parseDataFromNanoAppMessage(NanoAppMessage message) {
mDidReceiveNanoAppMessage.set(true);
if (message.getMessageType()
- != ChreCrossValidationWifi.MessageType.STEP_RESULT_VALUE) {
- setErrorStr(String.format("Received message with message type %d when expecting %d",
- message.getMessageType(),
- ChreCrossValidationWifi.MessageType.STEP_RESULT_VALUE));
- }
- ChreTestCommon.TestResult testResult = null;
- try {
- testResult = ChreTestCommon.TestResult.parseFrom(message.getMessageBody());
- } catch (InvalidProtocolBufferException e) {
- setErrorStr("Error parsing protobuff: " + e);
- mAwaitDataLatch.countDown();
- return;
- }
- boolean success = getSuccessFromTestResult(testResult);
- if (mStep.get() == Step.SETUP || mStep.get() == Step.VALIDATE) {
- if (success) {
- Log.i(TAG, getCurrentStepName() + " step success");
- } else {
- setErrorStr(getCurrentStepName() + " step failed: "
- + testResult.getErrorMessage().toStringUtf8());
+ == ChreCrossValidationWifi.MessageType.STEP_RESULT_VALUE) {
+ ChreTestCommon.TestResult testResult = null;
+ try {
+ testResult = ChreTestCommon.TestResult.parseFrom(message.getMessageBody());
+ } catch (InvalidProtocolBufferException e) {
+ setErrorStr("Error parsing protobuff: " + e);
+ mAwaitDataLatch.countDown();
+ return;
}
- } else { // mStep.get() == Step.INIT
- setErrorStr("Received a step result message when no phase set yet.");
+ boolean success = getSuccessFromTestResult(testResult);
+ if (mStep.get() == Step.SETUP || mStep.get() == Step.VALIDATE) {
+ if (success) {
+ Log.i(TAG, getCurrentStepName() + " step success");
+ } else {
+ setErrorStr(getCurrentStepName() + " step failed: "
+ + testResult.getErrorMessage().toStringUtf8());
+ }
+ } else {
+ setErrorStr("Received a step result message during step " + getCurrentStepName());
+ }
+ } else if (message.getMessageType()
+ == ChreCrossValidationWifi.MessageType.WIFI_CAPABILITIES_VALUE) {
+ if (mStep.get() != Step.CAPABILITIES) {
+ setErrorStr("Received a capabilities message during step " + getCurrentStepName());
+ }
+ ChreCrossValidationWifi.WifiCapabilities capabilities = null;
+ try {
+ capabilities = ChreCrossValidationWifi.WifiCapabilities.parseFrom(
+ message.getMessageBody());
+ } catch (InvalidProtocolBufferException e) {
+ setErrorStr("Error parsing protobuff: " + e);
+ mAwaitDataLatch.countDown();
+ return;
+ }
+ mWifiCapabilities.set(capabilities);
+ } else {
+ setErrorStr(String.format("Received message with unexpected type: %d",
+ message.getMessageType()));
}
// Each message should countdown the latch no matter success or fail
mAwaitDataLatch.countDown();