Merge "Adjust mock thermal HAL 2.0 mock data"
diff --git a/audio/5.0/config/api/current.txt b/audio/5.0/config/api/current.txt
index 17f38c1..c665781 100644
--- a/audio/5.0/config/api/current.txt
+++ b/audio/5.0/config/api/current.txt
@@ -114,6 +114,7 @@
enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX;
enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE;
enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX_HD;
+ enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX_TWSP;
enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_CELT;
enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD;
enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_DSD;
diff --git a/audio/5.0/config/audio_policy_configuration.xsd b/audio/5.0/config/audio_policy_configuration.xsd
index c580b25..2e1a722 100644
--- a/audio/5.0/config/audio_policy_configuration.xsd
+++ b/audio/5.0/config/audio_policy_configuration.xsd
@@ -374,6 +374,7 @@
<xs:enumeration value="AUDIO_FORMAT_APTX_ADAPTIVE"/>
<xs:enumeration value="AUDIO_FORMAT_LHDC"/>
<xs:enumeration value="AUDIO_FORMAT_LHDC_LL"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_TWSP"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="extendableAudioFormat">
diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal
index 8f8a888..e1279ee 100644
--- a/audio/common/5.0/types.hal
+++ b/audio/common/5.0/types.hal
@@ -146,6 +146,7 @@
*/
ECHO_REFERENCE = 1997,
FM_TUNER = 1998,
+ HOTWORD = 1999,
};
typedef int32_t AudioSession;
@@ -240,6 +241,7 @@
APTX_ADAPTIVE = 0x27000000UL,
LHDC = 0x28000000UL,
LHDC_LL = 0x29000000UL,
+ APTX_TWSP = 0x2A000000UL,
/** Deprecated */
MAIN_MASK = 0xFF000000UL,
@@ -416,9 +418,9 @@
OUT_2POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT |
OUT_LOW_FREQUENCY),
- OUT_3POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT |
+ OUT_3POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER |
OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
- OUT_3POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT |
+ OUT_3POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER |
OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT |
OUT_LOW_FREQUENCY),
OUT_QUAD = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
@@ -517,7 +519,23 @@
INDEX_MASK_5 = INDEX_HDR | ((1 << 5) - 1),
INDEX_MASK_6 = INDEX_HDR | ((1 << 6) - 1),
INDEX_MASK_7 = INDEX_HDR | ((1 << 7) - 1),
- INDEX_MASK_8 = INDEX_HDR | ((1 << 8) - 1)
+ INDEX_MASK_8 = INDEX_HDR | ((1 << 8) - 1),
+ INDEX_MASK_9 = INDEX_HDR | ((1 << 9) - 1),
+ INDEX_MASK_10 = INDEX_HDR | ((1 << 10) - 1),
+ INDEX_MASK_11 = INDEX_HDR | ((1 << 11) - 1),
+ INDEX_MASK_12 = INDEX_HDR | ((1 << 12) - 1),
+ INDEX_MASK_13 = INDEX_HDR | ((1 << 13) - 1),
+ INDEX_MASK_14 = INDEX_HDR | ((1 << 14) - 1),
+ INDEX_MASK_15 = INDEX_HDR | ((1 << 15) - 1),
+ INDEX_MASK_16 = INDEX_HDR | ((1 << 16) - 1),
+ INDEX_MASK_17 = INDEX_HDR | ((1 << 17) - 1),
+ INDEX_MASK_18 = INDEX_HDR | ((1 << 18) - 1),
+ INDEX_MASK_19 = INDEX_HDR | ((1 << 19) - 1),
+ INDEX_MASK_20 = INDEX_HDR | ((1 << 20) - 1),
+ INDEX_MASK_21 = INDEX_HDR | ((1 << 21) - 1),
+ INDEX_MASK_22 = INDEX_HDR | ((1 << 22) - 1),
+ INDEX_MASK_23 = INDEX_HDR | ((1 << 23) - 1),
+ INDEX_MASK_24 = INDEX_HDR | ((1 << 24) - 1),
};
/**
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 3efaaec..b04d096 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -989,6 +989,7 @@
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
*/
HVAC_TEMPERATURE_DISPLAY_UNITS = (
0x050E
@@ -1138,7 +1139,6 @@
* Indicates which units the car is using to display fuel volume to the user. Eg. Liter or
* Gallon.
*
- * Distance units are defined in VehicleUnit.
* VehiclePropConfig.configArray is used to indicate the supported fuel volume display units.
* Volume units are defined in VehicleUnit.
* For example: configArray[0] = 0x41 // LITER
@@ -1159,7 +1159,6 @@
* Indicates which units the car is using to display tire pressure to the user. Eg. PSI, Bar or
* Kilopascal.
*
- * Distance units are defined in VehicleUnit.
* VehiclePropConfig.configArray is used to indicate the supported pressure display units.
* Pressure units are defined in VehicleUnit.
* For example: configArray[0] = 0x70 // KILOPASCAL
@@ -1181,7 +1180,6 @@
* Indicates which units the car is using to display EV battery information to the user. Eg.
* watt-hours(Wh), kilowatt-hours(kWh) or ampere-hours(Ah).
*
- * Distance units are defined in VehicleUnit.
* VehiclePropConfig.configArray is used to indicate the supported electrical energy units.
* Electrical energy units are defined in VehicleUnit.
* For example: configArray[0] = 0x60 // watt-hours
@@ -1198,6 +1196,22 @@
| VehicleArea:GLOBAL),
/**
+ * Fuel consumption units for display
+ *
+ * Indicates type of units the car is using to display fuel consumption information to user
+ * True indicates units are distance over volume such as MPG.
+ * False indicates units are volume over distance such as L/100KM.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME = (
+ 0x0604
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:BOOLEAN
+ | VehicleArea:GLOBAL),
+
+ /**
* Outside temperature
*
* @change_mode VehiclePropertyChangeMode:CONTINUOUS
@@ -2433,7 +2447,7 @@
ERROR = 4,
};
-enum VehicleApPowerStateConfigFlag : int32_t /* NOTE: type is guessed */ {
+enum VehicleApPowerStateConfigFlag : int32_t {
/**
* AP can enter deep sleep state. If not set, AP will always shutdown from
* VehicleApPowerState#SHUTDOWN_PREPARE power state.
@@ -2587,7 +2601,11 @@
KELVIN = 0x32,
MILLILITER = 0x40,
LITER = 0x41,
+
+ /** deprecated. Use US_GALLON instead. */
GALLON = 0x42,
+ US_GALLON = 0x42,
+ IMPERIAL_GALLON= 0x43,
NANO_SECS = 0x50,
SECS = 0x53,
YEAR = 0x59,
diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal
index cd368fa..180d829 100644
--- a/biometrics/face/1.0/IBiometricsFace.hal
+++ b/biometrics/face/1.0/IBiometricsFace.hal
@@ -59,7 +59,9 @@
*
* @param userId A non-negative user identifier that must be unique and
* persistent for a given user.
- * @param storePath filesystem path to the template storage directory.
+ * @param storePath absolute filesystem path to the template storage
+ * directory. This must be the /data/vendor_de/<user>/facedata
+ * directory specified by the SeLinux policy.
*/
@callflow(next={"authenticate", "generateChallenge", "enumerate", "remove"})
setActiveUser(int32_t userId, string storePath) generates (Status status);
@@ -159,8 +161,8 @@
* @param enabled True to enable the feature, false to disable.
* @param hat A valid Hardware Authentication Token, generated as a result
* of getChallenge().
- * @param faceId the ID of the enrollment returned by enroll() for the
- * feature to update.
+ * @param faceId the ID of the enrollment returned by onEnrollResult() for
+ * the feature to update.
* @return status The status of this method call.
*/
setFeature(Feature feature, bool enabled, vec<uint8_t> hat, uint32_t faceId)
diff --git a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal
index 969bc68..d7c317d 100644
--- a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal
+++ b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal
@@ -95,13 +95,10 @@
*
* @param deviceId A unique id associated with the HAL implementation
* service that processed this removal.
- * @param faceId The id of the face template that was removed.
+ * @param removed A list of ids that were removed.
* @param userId The active user id for the removed face template.
- * @param remaining The number of face templates remaining after this
- * removal, or 0 if there are no more.
*/
- oneway onRemoved(uint64_t deviceId, uint32_t faceId, int32_t userId,
- uint32_t remaining);
+ oneway onRemoved(uint64_t deviceId, vec<uint32_t> removed, int32_t userId);
/**
* A callback invoked to enumerate all current face templates.
diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal
index 8c4a4e9..de6b99e 100644
--- a/biometrics/face/1.0/types.hal
+++ b/biometrics/face/1.0/types.hal
@@ -340,9 +340,14 @@
START = 20,
/**
+ * The sensor is dirty. The user should be informed to clean the sensor.
+ */
+ SENSOR_DIRTY = 21,
+
+ /**
* Used to enable a vendor-specific acquisition message.
*/
- VENDOR = 21
+ VENDOR = 22
};
/**
@@ -375,4 +380,4 @@
* This value is only meaningful if status is OK.
*/
bool value;
-};
\ No newline at end of file
+};
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index 795a1ae..40961f7 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -104,7 +104,7 @@
return Return<void>();
}
- Return<void> onRemoved(uint64_t, uint32_t, int32_t, uint32_t) override {
+ Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
ALOGD("Removed callback called.");
return Return<void>();
}
@@ -155,12 +155,9 @@
public:
explicit RemoveCallback(int32_t userId) : removeUserId(userId) {}
- Return<void> onRemoved(uint64_t, uint32_t, int32_t userId, uint32_t remaining) override {
+ Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t userId) override {
EXPECT_EQ(removeUserId, userId);
promise.set_value();
- if (remaining == 0UL) {
- promise.set_value();
- }
return Return<void>();
}
diff --git a/broadcastradio/2.0/default/BroadcastRadio.cpp b/broadcastradio/2.0/default/BroadcastRadio.cpp
index 28a0dd5..88a726f 100644
--- a/broadcastradio/2.0/default/BroadcastRadio.cpp
+++ b/broadcastradio/2.0/default/BroadcastRadio.cpp
@@ -49,6 +49,7 @@
static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
static_cast<uint32_t>(IdentifierType::RDS_PI),
static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
+ static_cast<uint32_t>(IdentifierType::DAB_SID_EXT),
});
prop.vendorInfo = hidl_vec<VendorKeyValue>({
{"com.google.dummy", "dummy"},
diff --git a/broadcastradio/2.0/default/VirtualRadio.cpp b/broadcastradio/2.0/default/VirtualRadio.cpp
index 0b65979..c59fd8f 100644
--- a/broadcastradio/2.0/default/VirtualRadio.cpp
+++ b/broadcastradio/2.0/default/VirtualRadio.cpp
@@ -28,6 +28,7 @@
using std::mutex;
using std::vector;
using utils::make_selector_amfm;
+using utils::make_selector_dab;
VirtualRadio gAmFmRadio(
"AM/FM radio mock",
@@ -41,6 +42,16 @@
{make_selector_amfm(106100), "106 KMEL", "Drake", "Marvins Room"},
});
+// clang-format off
+VirtualRadio gDabRadio(
+ "DAB radio mock",
+ {
+ {make_selector_dab(12345, 225648), "BBC Radio 1", "Khalid", "Talk"}, // 12B
+ {make_selector_dab(22345, 222064), "Classic FM", "Jean Sibelius", "Andante Festivo"}, // 11D
+ {make_selector_dab(32345, 222064), "Absolute Radio", "Coldplay", "Clocks"}, // 11D
+ });
+// clang-format on
+
VirtualRadio::VirtualRadio(const std::string& name, const vector<VirtualProgram>& initialList)
: mName(name), mPrograms(initialList) {}
diff --git a/broadcastradio/2.0/default/VirtualRadio.h b/broadcastradio/2.0/default/VirtualRadio.h
index 9c07816..6fa70c5 100644
--- a/broadcastradio/2.0/default/VirtualRadio.h
+++ b/broadcastradio/2.0/default/VirtualRadio.h
@@ -52,6 +52,9 @@
/** AM/FM virtual radio space. */
extern VirtualRadio gAmFmRadio;
+/** DAB virtual radio space. */
+extern VirtualRadio gDabRadio;
+
} // namespace implementation
} // namespace V2_0
} // namespace broadcastradio
diff --git a/broadcastradio/2.0/default/service.cpp b/broadcastradio/2.0/default/service.cpp
index af96dad..349aba2 100644
--- a/broadcastradio/2.0/default/service.cpp
+++ b/broadcastradio/2.0/default/service.cpp
@@ -23,6 +23,7 @@
using android::hardware::joinRpcThreadpool;
using android::hardware::broadcastradio::V2_0::implementation::BroadcastRadio;
using android::hardware::broadcastradio::V2_0::implementation::gAmFmRadio;
+using android::hardware::broadcastradio::V2_0::implementation::gDabRadio;
int main() {
android::base::SetDefaultTag("BcRadioDef");
@@ -30,8 +31,13 @@
configureRpcThreadpool(4, true);
BroadcastRadio broadcastRadio(gAmFmRadio);
- auto status = broadcastRadio.registerAsService();
- CHECK_EQ(status, android::OK) << "Failed to register Broadcast Radio HAL implementation";
+ auto amFmStatus = broadcastRadio.registerAsService("amfm");
+ CHECK_EQ(amFmStatus, android::OK)
+ << "Failed to register Broadcast Radio AM/FM HAL implementation";
+
+ BroadcastRadio dabRadio(gDabRadio);
+ auto dabStatus = dabRadio.registerAsService("dab");
+ CHECK_EQ(dabStatus, android::OK) << "Failed to register Broadcast Radio DAB HAL implementation";
joinRpcThreadpool();
return 1; // joinRpcThreadpool shouldn't exit
diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp
index 7892653..43f272e 100644
--- a/broadcastradio/common/utils2x/Utils.cpp
+++ b/broadcastradio/common/utils2x/Utils.cpp
@@ -299,6 +299,20 @@
return sel;
}
+ProgramSelector make_selector_dab(uint32_t sidExt, uint32_t ensemble) {
+ ProgramSelector sel = {};
+ // TODO(maryabad): Have a helper function to create the sidExt instead of
+ // passing the whole identifier here. Something like make_dab_sid_ext.
+ sel.primaryId = make_identifier(IdentifierType::DAB_SID_EXT, sidExt);
+ hidl_vec<ProgramIdentifier> secondaryIds = {
+ make_identifier(IdentifierType::DAB_ENSEMBLE, ensemble),
+ // TODO(maryabad): Include frequency here when the helper method to
+ // translate between ensemble and frequency is implemented.
+ };
+ sel.secondaryIds = secondaryIds;
+ return sel;
+}
+
Metadata make_metadata(MetadataKey key, int64_t value) {
Metadata meta = {};
meta.key = static_cast<uint32_t>(key);
diff --git a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
index c4aecb2..f4e0732 100644
--- a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
+++ b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
@@ -126,6 +126,7 @@
V2_0::ProgramIdentifier make_identifier(V2_0::IdentifierType type, uint64_t value);
V2_0::ProgramSelector make_selector_amfm(uint32_t frequency);
+V2_0::ProgramSelector make_selector_dab(uint32_t sidExt, uint32_t ensemble);
V2_0::Metadata make_metadata(V2_0::MetadataKey key, int64_t value);
V2_0::Metadata make_metadata(V2_0::MetadataKey key, std::string value);
diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS
index 369b204..f112576 100644
--- a/camera/common/1.0/default/OWNERS
+++ b/camera/common/1.0/default/OWNERS
@@ -1,7 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-jchowdhary@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av/camera:/OWNERS
diff --git a/camera/device/1.0/default/OWNERS b/camera/device/1.0/default/OWNERS
index 369b204..f48a95c 100644
--- a/camera/device/1.0/default/OWNERS
+++ b/camera/device/1.0/default/OWNERS
@@ -1,7 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-jchowdhary@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
diff --git a/camera/device/3.2/default/OWNERS b/camera/device/3.2/default/OWNERS
index 369b204..f48a95c 100644
--- a/camera/device/3.2/default/OWNERS
+++ b/camera/device/3.2/default/OWNERS
@@ -1,7 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-jchowdhary@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
diff --git a/camera/device/3.3/default/OWNERS b/camera/device/3.3/default/OWNERS
index 369b204..f48a95c 100644
--- a/camera/device/3.3/default/OWNERS
+++ b/camera/device/3.3/default/OWNERS
@@ -1,7 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-jchowdhary@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index 0f23657..3f04751 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -38,9 +38,8 @@
// Other formats to consider in the future:
// * V4L2_PIX_FMT_YVU420 (== YV12)
// * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats)
-const std::array<uint32_t, /*size*/1> kSupportedFourCCs {{
- V4L2_PIX_FMT_MJPEG
-}}; // double braces required in C++11
+const std::array<uint32_t, /*size*/ 2> kSupportedFourCCs{
+ {V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_Z16}}; // double braces required in C++11
constexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times.
constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds
@@ -231,6 +230,13 @@
mCameraCharacteristics.clear();
return ret;
}
+
+ ret = initAvailableCapabilities(&mCameraCharacteristics);
+ if (ret != OK) {
+ ALOGE("%s: init available capabilities key failed: errorno %d", __FUNCTION__, ret);
+ mCameraCharacteristics.clear();
+ return ret;
+ }
}
return OK;
}
@@ -244,6 +250,39 @@
} \
} while (0)
+status_t ExternalCameraDevice::initAvailableCapabilities(
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
+
+ if (mSupportedFormats.empty()) {
+ ALOGE("%s: Supported formats list is empty", __FUNCTION__);
+ return UNKNOWN_ERROR;
+ }
+
+ bool hasDepth = false;
+ bool hasColor = false;
+ for (const auto& fmt : mSupportedFormats) {
+ switch (fmt.fourcc) {
+ case V4L2_PIX_FMT_Z16: hasDepth = true; break;
+ case V4L2_PIX_FMT_MJPEG: hasColor = true; break;
+ default: ALOGW("%s: Unsupported format found", __FUNCTION__);
+ }
+ }
+
+ std::vector<uint8_t> availableCapabilities;
+ if (hasDepth) {
+ availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT);
+ }
+ if (hasColor) {
+ availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
+ }
+ if(!availableCapabilities.empty()) {
+ UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities.data(),
+ availableCapabilities.size());
+ }
+
+ return OK;
+}
+
status_t ExternalCameraDevice::initDefaultCharsKeys(
::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
@@ -330,12 +369,6 @@
&noiseReductionMode, 1);
UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
- // android.request
- const uint8_t availableCapabilities[] = {
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
- UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities,
- ARRAY_SIZE(availableCapabilities));
-
const int32_t partialResultCount = 1;
UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
@@ -544,9 +577,11 @@
return OK;
}
-status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
- ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
- initSupportedFormatsLocked(fd);
+template <size_t SIZE>
+status_t ExternalCameraDevice::initOutputCharskeysByFormat(
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata,
+ uint32_t fourcc, const std::array<int, SIZE>& halFormats,
+ int streamConfigTag, int streamConfiguration, int minFrameDuration, int stallDuration) {
if (mSupportedFormats.empty()) {
ALOGE("%s: Init supported format list failed", __FUNCTION__);
return UNKNOWN_ERROR;
@@ -555,22 +590,17 @@
std::vector<int32_t> streamConfigurations;
std::vector<int64_t> minFrameDurations;
std::vector<int64_t> stallDurations;
- int32_t maxFps = std::numeric_limits<int32_t>::min();
- int32_t minFps = std::numeric_limits<int32_t>::max();
- std::set<int32_t> framerates;
-
- std::array<int, /*size*/3> halFormats{{
- HAL_PIXEL_FORMAT_BLOB,
- HAL_PIXEL_FORMAT_YCbCr_420_888,
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
for (const auto& supportedFormat : mSupportedFormats) {
+ if (supportedFormat.fourcc != fourcc) {
+ // Skip 4CCs not meant for the halFormats
+ continue;
+ }
for (const auto& format : halFormats) {
streamConfigurations.push_back(format);
streamConfigurations.push_back(supportedFormat.width);
streamConfigurations.push_back(supportedFormat.height);
- streamConfigurations.push_back(
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
+ streamConfigurations.push_back(streamConfigTag);
}
int64_t minFrameDuration = std::numeric_limits<int64_t>::max();
@@ -582,14 +612,6 @@
if (frameDuration < minFrameDuration) {
minFrameDuration = frameDuration;
}
- int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
- if (minFps > frameRateInt) {
- minFps = frameRateInt;
- }
- if (maxFps < frameRateInt) {
- maxFps = frameRateInt;
- }
- framerates.insert(frameRateInt);
}
for (const auto& format : halFormats) {
@@ -613,6 +635,30 @@
}
}
+ UPDATE(streamConfiguration, streamConfigurations.data(), streamConfigurations.size());
+
+ UPDATE(minFrameDuration, minFrameDurations.data(), minFrameDurations.size());
+
+ UPDATE(stallDuration, stallDurations.data(), stallDurations.size());
+
+ return true;
+}
+
+bool ExternalCameraDevice::calculateMinFps(
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
+ std::set<int32_t> framerates;
+ int32_t minFps = std::numeric_limits<int32_t>::max();
+
+ for (const auto& supportedFormat : mSupportedFormats) {
+ for (const auto& fr : supportedFormat.frameRates) {
+ int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
+ if (minFps > frameRateInt) {
+ minFps = frameRateInt;
+ }
+ framerates.insert(frameRateInt);
+ }
+ }
+
std::vector<int32_t> fpsRanges;
// FPS ranges
for (const auto& framerate : framerates) {
@@ -626,17 +672,60 @@
UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
fpsRanges.size());
- UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- streamConfigurations.data(), streamConfigurations.size());
-
- UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
- minFrameDurations.data(), minFrameDurations.size());
-
- UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stallDurations.data(),
- stallDurations.size());
-
UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
+ return true;
+}
+
+status_t ExternalCameraDevice::initOutputCharsKeys(
+ int fd, ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
+ initSupportedFormatsLocked(fd);
+ if (mSupportedFormats.empty()) {
+ ALOGE("%s: Init supported format list failed", __FUNCTION__);
+ return UNKNOWN_ERROR;
+ }
+
+ bool hasDepth = false;
+ bool hasColor = false;
+
+ // For V4L2_PIX_FMT_Z16
+ std::array<int, /*size*/ 1> halDepthFormats{{HAL_PIXEL_FORMAT_Y16}};
+ // For V4L2_PIX_FMT_MJPEG
+ std::array<int, /*size*/ 3> halFormats{{HAL_PIXEL_FORMAT_BLOB, HAL_PIXEL_FORMAT_YCbCr_420_888,
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
+
+ for (const auto& supportedFormat : mSupportedFormats) {
+ switch (supportedFormat.fourcc) {
+ case V4L2_PIX_FMT_Z16:
+ hasDepth = true;
+ break;
+ case V4L2_PIX_FMT_MJPEG:
+ hasColor = true;
+ break;
+ default:
+ ALOGW("%s: format %c%c%c%c is not supported!", __FUNCTION__,
+ supportedFormat.fourcc & 0xFF, (supportedFormat.fourcc >> 8) & 0xFF,
+ (supportedFormat.fourcc >> 16) & 0xFF, (supportedFormat.fourcc >> 24) & 0xFF);
+ }
+ }
+
+ if (hasDepth) {
+ initOutputCharskeysByFormat(metadata, V4L2_PIX_FMT_Z16, halDepthFormats,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
+ }
+ if (hasColor) {
+ initOutputCharskeysByFormat(metadata, V4L2_PIX_FMT_MJPEG, halFormats,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ ANDROID_SCALER_AVAILABLE_STALL_DURATIONS);
+ }
+
+ calculateMinFps(metadata);
+
SupportedV4L2Format maximumFormat {.width = 0, .height = 0};
for (const auto& supportedFormat : mSupportedFormats) {
if (supportedFormat.width >= maximumFormat.width &&
@@ -758,11 +847,12 @@
sortedFmts = out;
}
-std::vector<SupportedV4L2Format>
-ExternalCameraDevice::getCandidateSupportedFormatsLocked(
- int fd, CroppingType cropType,
- const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
- const Size& minStreamSize) {
+std::vector<SupportedV4L2Format> ExternalCameraDevice::getCandidateSupportedFormatsLocked(
+ int fd, CroppingType cropType,
+ const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
+ const std::vector<ExternalCameraConfig::FpsLimitation>& depthFpsLimits,
+ const Size& minStreamSize,
+ bool depthEnabled) {
std::vector<SupportedV4L2Format> outFmts;
struct v4l2_fmtdesc fmtdesc {
.index = 0,
@@ -808,28 +898,10 @@
.fourcc = fmtdesc.pixelformat
};
- double fpsUpperBound = -1.0;
- for (const auto& limit : fpsLimits) {
- if (cropType == VERTICAL) {
- if (format.width <= limit.size.width) {
- fpsUpperBound = limit.fpsUpperBound;
- break;
- }
- } else { // HORIZONTAL
- if (format.height <= limit.size.height) {
- fpsUpperBound = limit.fpsUpperBound;
- break;
- }
- }
-
- }
- if (fpsUpperBound < 0.f) {
- continue;
- }
-
- getFrameRateList(fd, fpsUpperBound, &format);
- if (!format.frameRates.empty()) {
- outFmts.push_back(format);
+ if (format.fourcc == V4L2_PIX_FMT_Z16 && depthEnabled) {
+ updateFpsBounds(fd, cropType, depthFpsLimits, format, outFmts);
+ } else {
+ updateFpsBounds(fd, cropType, fpsLimits, format, outFmts);
}
}
}
@@ -841,12 +913,39 @@
return outFmts;
}
-void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
+void ExternalCameraDevice::updateFpsBounds(
+ int fd, CroppingType cropType,
+ const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits, SupportedV4L2Format format,
+ std::vector<SupportedV4L2Format>& outFmts) {
+ double fpsUpperBound = -1.0;
+ for (const auto& limit : fpsLimits) {
+ if (cropType == VERTICAL) {
+ if (format.width <= limit.size.width) {
+ fpsUpperBound = limit.fpsUpperBound;
+ break;
+ }
+ } else { // HORIZONTAL
+ if (format.height <= limit.size.height) {
+ fpsUpperBound = limit.fpsUpperBound;
+ break;
+ }
+ }
+ }
+ if (fpsUpperBound < 0.f) {
+ return;
+ }
- std::vector<SupportedV4L2Format> horizontalFmts =
- getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits, mCfg.minStreamSize);
- std::vector<SupportedV4L2Format> verticalFmts =
- getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits, mCfg.minStreamSize);
+ getFrameRateList(fd, fpsUpperBound, &format);
+ if (!format.frameRates.empty()) {
+ outFmts.push_back(format);
+ }
+}
+
+void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
+ std::vector<SupportedV4L2Format> horizontalFmts = getCandidateSupportedFormatsLocked(
+ fd, HORIZONTAL, mCfg.fpsLimits, mCfg.depthFpsLimits, mCfg.minStreamSize, mCfg.depthEnabled);
+ std::vector<SupportedV4L2Format> verticalFmts = getCandidateSupportedFormatsLocked(
+ fd, VERTICAL, mCfg.fpsLimits, mCfg.depthFpsLimits, mCfg.minStreamSize, mCfg.depthEnabled);
size_t horiSize = horizontalFmts.size();
size_t vertSize = verticalFmts.size();
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 66b17db..dc5579a 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -853,7 +853,7 @@
result.outputBuffers[i].bufferId = req->buffers[i].bufferId;
if (req->buffers[i].fenceTimeout) {
result.outputBuffers[i].status = BufferStatus::ERROR;
- if (req->buffers[i].acquireFence > 0) {
+ if (req->buffers[i].acquireFence >= 0) {
native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
handle->data[0] = req->buffers[i].acquireFence;
result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
@@ -862,7 +862,7 @@
} else {
result.outputBuffers[i].status = BufferStatus::OK;
// TODO: refactor
- if (req->buffers[i].acquireFence > 0) {
+ if (req->buffers[i].acquireFence >= 0) {
native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
handle->data[0] = req->buffers[i].acquireFence;
result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
@@ -1778,7 +1778,7 @@
/* Unlock the HAL jpeg code buffer */
int relFence = sHandleImporter.unlock(*(halBuf.bufPtr));
- if (relFence > 0) {
+ if (relFence >= 0) {
halBuf.acquireFence = relFence;
}
@@ -1819,7 +1819,7 @@
return false;
};
- if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) {
+ if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG && req->frameIn->mFourcc != V4L2_PIX_FMT_Z16) {
return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__,
req->frameIn->mFourcc & 0xFF,
(req->frameIn->mFourcc >> 8) & 0xFF,
@@ -1844,29 +1844,26 @@
}
// TODO: in some special case maybe we can decode jpg directly to gralloc output?
- ATRACE_BEGIN("MJPGtoI420");
- res = libyuv::MJPGToI420(
- inData, inDataSize,
- static_cast<uint8_t*>(mYu12FrameLayout.y),
- mYu12FrameLayout.yStride,
- static_cast<uint8_t*>(mYu12FrameLayout.cb),
- mYu12FrameLayout.cStride,
- static_cast<uint8_t*>(mYu12FrameLayout.cr),
- mYu12FrameLayout.cStride,
- mYu12Frame->mWidth, mYu12Frame->mHeight,
- mYu12Frame->mWidth, mYu12Frame->mHeight);
- ATRACE_END();
+ if (req->frameIn->mFourcc == V4L2_PIX_FMT_MJPEG) {
+ ATRACE_BEGIN("MJPGtoI420");
+ int res = libyuv::MJPGToI420(
+ inData, inDataSize, static_cast<uint8_t*>(mYu12FrameLayout.y), mYu12FrameLayout.yStride,
+ static_cast<uint8_t*>(mYu12FrameLayout.cb), mYu12FrameLayout.cStride,
+ static_cast<uint8_t*>(mYu12FrameLayout.cr), mYu12FrameLayout.cStride,
+ mYu12Frame->mWidth, mYu12Frame->mHeight, mYu12Frame->mWidth, mYu12Frame->mHeight);
+ ATRACE_END();
- if (res != 0) {
- // For some webcam, the first few V4L2 frames might be malformed...
- ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res);
- lk.unlock();
- Status st = parent->processCaptureRequestError(req);
- if (st != Status::OK) {
- return onDeviceError("%s: failed to process capture request error!", __FUNCTION__);
+ if (res != 0) {
+ // For some webcam, the first few V4L2 frames might be malformed...
+ ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res);
+ lk.unlock();
+ Status st = parent->processCaptureRequestError(req);
+ if (st != Status::OK) {
+ return onDeviceError("%s: failed to process capture request error!", __FUNCTION__);
+ }
+ signalRequestDone();
+ return true;
}
- signalRequestDone();
- return true;
}
ATRACE_BEGIN("Wait for BufferRequest done");
@@ -1885,7 +1882,7 @@
if (*(halBuf.bufPtr) == nullptr) {
ALOGW("%s: buffer for stream %d missing", __FUNCTION__, halBuf.streamId);
halBuf.fenceTimeout = true;
- } else if (halBuf.acquireFence != -1) {
+ } else if (halBuf.acquireFence >= 0) {
int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs);
if (ret) {
halBuf.fenceTimeout = true;
@@ -1910,6 +1907,16 @@
__FUNCTION__, ret);
}
} break;
+ case PixelFormat::Y16: {
+ void* outLayout = sHandleImporter.lock(*(halBuf.bufPtr), halBuf.usage, inDataSize);
+
+ std::memcpy(outLayout, inData, inDataSize);
+
+ int relFence = sHandleImporter.unlock(*(halBuf.bufPtr));
+ if (relFence >= 0) {
+ halBuf.acquireFence = relFence;
+ }
+ } break;
case PixelFormat::YCBCR_420_888:
case PixelFormat::YV12: {
IMapper::Rect outRect {0, 0,
@@ -1950,7 +1957,7 @@
return onDeviceError("%s: format coversion failed!", __FUNCTION__);
}
int relFence = sHandleImporter.unlock(*(halBuf.bufPtr));
- if (relFence > 0) {
+ if (relFence >= 0) {
halBuf.acquireFence = relFence;
}
} break;
@@ -2164,7 +2171,8 @@
}
bool ExternalCameraDeviceSession::isSupported(const Stream& stream,
- const std::vector<SupportedV4L2Format>& supportedFormats) {
+ const std::vector<SupportedV4L2Format>& supportedFormats,
+ const ExternalCameraConfig& devCfg) {
int32_t ds = static_cast<int32_t>(stream.dataSpace);
PixelFormat fmt = stream.format;
uint32_t width = stream.width;
@@ -2181,11 +2189,6 @@
return false;
}
- if (ds & Dataspace::DEPTH) {
- ALOGI("%s: does not support depth output", __FUNCTION__);
- return false;
- }
-
switch (fmt) {
case PixelFormat::BLOB:
if (ds != static_cast<int32_t>(Dataspace::V0_JFIF)) {
@@ -2199,6 +2202,16 @@
// TODO: check what dataspace we can support here.
// intentional no-ops.
break;
+ case PixelFormat::Y16:
+ if (!devCfg.depthEnabled) {
+ ALOGI("%s: Depth is not Enabled", __FUNCTION__);
+ return false;
+ }
+ if (!(ds & Dataspace::DEPTH)) {
+ ALOGI("%s: Y16 supports only dataSpace DEPTH", __FUNCTION__);
+ return false;
+ }
+ break;
default:
ALOGI("%s: does not support format %x", __FUNCTION__, fmt);
return false;
@@ -2544,7 +2557,8 @@
Status ExternalCameraDeviceSession::isStreamCombinationSupported(
const V3_2::StreamConfiguration& config,
- const std::vector<SupportedV4L2Format>& supportedFormats) {
+ const std::vector<SupportedV4L2Format>& supportedFormats,
+ const ExternalCameraConfig& devCfg) {
if (config.operationMode != StreamConfigurationMode::NORMAL_MODE) {
ALOGE("%s: unsupported operation mode: %d", __FUNCTION__, config.operationMode);
return Status::ILLEGAL_ARGUMENT;
@@ -2559,7 +2573,7 @@
int numStallStream = 0;
for (const auto& stream : config.streams) {
// Check if the format/width/height combo is supported
- if (!isSupported(stream, supportedFormats)) {
+ if (!isSupported(stream, supportedFormats, devCfg)) {
return Status::ILLEGAL_ARGUMENT;
}
if (stream.format == PixelFormat::BLOB) {
@@ -2590,7 +2604,7 @@
uint32_t blobBufferSize) {
ATRACE_CALL();
- Status status = isStreamCombinationSupported(config, mSupportedFormats);
+ Status status = isStreamCombinationSupported(config, mSupportedFormats, mCfg);
if (status != Status::OK) {
return status;
}
@@ -2744,6 +2758,7 @@
case PixelFormat::BLOB:
case PixelFormat::YCBCR_420_888:
case PixelFormat::YV12: // Used by SurfaceTexture
+ case PixelFormat::Y16:
// No override
out->streams[i].v3_2.overrideFormat = config.streams[i].format;
break;
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 0941052..e25deff 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -21,7 +21,6 @@
#include <sys/mman.h>
#include <linux/videodev2.h>
#include "ExternalCameraUtils.h"
-#include "tinyxml2.h" // XML parsing
namespace android {
namespace hardware {
@@ -245,28 +244,28 @@
if (fpsList == nullptr) {
ALOGI("%s: no fps list specified", __FUNCTION__);
} else {
- std::vector<FpsLimitation> limits;
- XMLElement *row = fpsList->FirstChildElement("Limit");
- while (row != nullptr) {
- FpsLimitation prevLimit {{0, 0}, 1000.0};
- FpsLimitation limit;
- limit.size = {
- row->UnsignedAttribute("width", /*Default*/0),
- row->UnsignedAttribute("height", /*Default*/0)};
- limit.fpsUpperBound = row->DoubleAttribute("fpsBound", /*Default*/1000.0);
- if (limit.size.width <= prevLimit.size.width ||
- limit.size.height <= prevLimit.size.height ||
- limit.fpsUpperBound >= prevLimit.fpsUpperBound) {
- ALOGE("%s: FPS limit list must have increasing size and decreasing fps!"
- " Prev %dx%d@%f, Current %dx%d@%f", __FUNCTION__,
- prevLimit.size.width, prevLimit.size.height, prevLimit.fpsUpperBound,
- limit.size.width, limit.size.height, limit.fpsUpperBound);
+ if (!updateFpsList(fpsList, ret.fpsLimits)) {
+ return ret;
+ }
+ }
+
+ XMLElement *depth = deviceCfg->FirstChildElement("Depth16Supported");
+ if (depth == nullptr) {
+ ret.depthEnabled = false;
+ ALOGI("%s: depth output is not enabled", __FUNCTION__);
+ } else {
+ ret.depthEnabled = depth->BoolAttribute("enabled", false);
+ }
+
+ if(ret.depthEnabled) {
+ XMLElement *depthFpsList = deviceCfg->FirstChildElement("DepthFpsList");
+ if (depthFpsList == nullptr) {
+ ALOGW("%s: no depth fps list specified", __FUNCTION__);
+ } else {
+ if(!updateFpsList(depthFpsList, ret.depthFpsLimits)) {
return ret;
}
- limits.push_back(limit);
- row = row->NextSiblingElement("Limit");
}
- ret.fpsLimits = limits;
}
XMLElement *minStreamSize = deviceCfg->FirstChildElement("MinimumStreamSize");
@@ -293,15 +292,48 @@
ALOGI("%s: fpsLimitList: %dx%d@%f", __FUNCTION__,
limit.size.width, limit.size.height, limit.fpsUpperBound);
}
+ for (const auto& limit : ret.depthFpsLimits) {
+ ALOGI("%s: depthFpsLimitList: %dx%d@%f", __FUNCTION__, limit.size.width, limit.size.height,
+ limit.fpsUpperBound);
+ }
ALOGI("%s: minStreamSize: %dx%d" , __FUNCTION__,
ret.minStreamSize.width, ret.minStreamSize.height);
return ret;
}
+bool ExternalCameraConfig::updateFpsList(tinyxml2::XMLElement* fpsList,
+ std::vector<FpsLimitation>& fpsLimits) {
+ using namespace tinyxml2;
+ std::vector<FpsLimitation> limits;
+ XMLElement* row = fpsList->FirstChildElement("Limit");
+ while (row != nullptr) {
+ FpsLimitation prevLimit{{0, 0}, 1000.0};
+ FpsLimitation limit;
+ limit.size = {row->UnsignedAttribute("width", /*Default*/ 0),
+ row->UnsignedAttribute("height", /*Default*/ 0)};
+ limit.fpsUpperBound = row->DoubleAttribute("fpsBound", /*Default*/ 1000.0);
+ if (limit.size.width <= prevLimit.size.width ||
+ limit.size.height <= prevLimit.size.height ||
+ limit.fpsUpperBound >= prevLimit.fpsUpperBound) {
+ ALOGE(
+ "%s: FPS limit list must have increasing size and decreasing fps!"
+ " Prev %dx%d@%f, Current %dx%d@%f",
+ __FUNCTION__, prevLimit.size.width, prevLimit.size.height, prevLimit.fpsUpperBound,
+ limit.size.width, limit.size.height, limit.fpsUpperBound);
+ return false;
+ }
+ limits.push_back(limit);
+ row = row->NextSiblingElement("Limit");
+ }
+ fpsLimits = limits;
+ return true;
+}
+
ExternalCameraConfig::ExternalCameraConfig() :
maxJpegBufSize(kDefaultJpegBufSize),
numVideoBuffers(kDefaultNumVideoBuffer),
numStillBuffers(kDefaultNumStillBuffer),
+ depthEnabled(false),
orientation(kDefaultOrientation) {
fpsLimits.push_back({/*Size*/{ 640, 480}, /*FPS upper bound*/30.0});
fpsLimits.push_back({/*Size*/{1280, 720}, /*FPS upper bound*/7.5});
diff --git a/camera/device/3.4/default/OWNERS b/camera/device/3.4/default/OWNERS
index 369b204..f48a95c 100644
--- a/camera/device/3.4/default/OWNERS
+++ b/camera/device/3.4/default/OWNERS
@@ -1,7 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-jchowdhary@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index 9cc55cb..71b7c17 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -194,7 +194,8 @@
int v4l2StreamOffLocked();
int setV4l2FpsLocked(double fps);
static Status isStreamCombinationSupported(const V3_2::StreamConfiguration& config,
- const std::vector<SupportedV4L2Format>& supportedFormats);
+ const std::vector<SupportedV4L2Format>& supportedFormats,
+ const ExternalCameraConfig& devCfg);
// TODO: change to unique_ptr for better tracking
sp<V4L2Frame> dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs); // Called with mLock hold
@@ -202,7 +203,8 @@
// Check if input Stream is one of supported stream setting on this device
static bool isSupported(const Stream& stream,
- const std::vector<SupportedV4L2Format>& supportedFormats);
+ const std::vector<SupportedV4L2Format>& supportedFormats,
+ const ExternalCameraConfig& cfg);
// Validate and import request's output buffers and acquire fence
virtual Status importRequestLocked(
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
index 719a3ed..bd79807 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
@@ -104,6 +104,9 @@
// Calls into virtual member function. Do not use it in constructor
status_t initCameraCharacteristics();
+ // Init available capabilities keys
+ status_t initAvailableCapabilities(
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
// Init non-device dependent keys
virtual status_t initDefaultCharsKeys(
::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
@@ -114,13 +117,30 @@
status_t initOutputCharsKeys(int fd,
::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
+ // Helper function for initOutputCharskeys
+ template <size_t SIZE>
+ status_t initOutputCharskeysByFormat(
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata*,
+ uint32_t fourcc, const std::array<int, SIZE>& formats,
+ int scaler_stream_config_tag,
+ int stream_configuration, int min_frame_duration, int stall_duration);
+
+ bool calculateMinFps(::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
+
static void getFrameRateList(int fd, double fpsUpperBound, SupportedV4L2Format* format);
+ static void updateFpsBounds(int fd, CroppingType cropType,
+ const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
+ SupportedV4L2Format format,
+ std::vector<SupportedV4L2Format>& outFmts);
+
// Get candidate supported formats list of input cropping type.
static std::vector<SupportedV4L2Format> getCandidateSupportedFormatsLocked(
int fd, CroppingType cropType,
const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
- const Size& minStreamSize);
+ const std::vector<ExternalCameraConfig::FpsLimitation>& depthFpsLimits,
+ const Size& minStreamSize,
+ bool depthEnabled);
// Trim supported format list by the cropping type. Also sort output formats by width/height
static void trimSupportedFormats(CroppingType cropType,
/*inout*/std::vector<SupportedV4L2Format>* pFmts);
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index 3b1ac96..341c622 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -17,12 +17,13 @@
#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMUTIL_H
#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMUTIL_H
-#include <inttypes.h>
-#include "utils/LightRefBase.h"
-#include <mutex>
-#include <vector>
-#include <unordered_set>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <inttypes.h>
+#include <mutex>
+#include <unordered_set>
+#include <vector>
+#include "tinyxml2.h" // XML parsing
+#include "utils/LightRefBase.h"
using android::hardware::graphics::mapper::V2_0::IMapper;
using android::hardware::graphics::mapper::V2_0::YCbCrLayout;
@@ -71,11 +72,15 @@
// Size of v4l2 buffer queue when streaming > kMaxVideoSize
uint32_t numStillBuffers;
+ // Indication that the device connected supports depth output
+ bool depthEnabled;
+
struct FpsLimitation {
Size size;
double fpsUpperBound;
};
std::vector<FpsLimitation> fpsLimits;
+ std::vector<FpsLimitation> depthFpsLimits;
// Minimum output stream size
Size minStreamSize;
@@ -85,6 +90,7 @@
private:
ExternalCameraConfig();
+ static bool updateFpsList(tinyxml2::XMLElement* fpsList, std::vector<FpsLimitation>& fpsLimits);
};
} // common
diff --git a/camera/device/3.5/default/ExternalCameraDevice.cpp b/camera/device/3.5/default/ExternalCameraDevice.cpp
index 6a0b51e..d0de1a4 100644
--- a/camera/device/3.5/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.5/default/ExternalCameraDevice.cpp
@@ -103,7 +103,7 @@
}
V3_2::StreamConfiguration streamConfig = {streamsV3_2, streams.operationMode};
auto status = ExternalCameraDeviceSession::isStreamCombinationSupported(streamConfig,
- mSupportedFormats);
+ mSupportedFormats, mCfg);
_hidl_cb(Status::OK, Status::OK == status);
return Void();
}
diff --git a/camera/device/3.5/default/OWNERS b/camera/device/3.5/default/OWNERS
index 369b204..f48a95c 100644
--- a/camera/device/3.5/default/OWNERS
+++ b/camera/device/3.5/default/OWNERS
@@ -1,7 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-jchowdhary@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
diff --git a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h
index d2b5e89..281f93a 100644
--- a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h
@@ -91,9 +91,10 @@
}
static Status isStreamCombinationSupported(const V3_2::StreamConfiguration& config,
- const std::vector<SupportedV4L2Format>& supportedFormats) {
+ const std::vector<SupportedV4L2Format>& supportedFormats,
+ const ExternalCameraConfig& devCfg) {
return V3_4::implementation::ExternalCameraDeviceSession::isStreamCombinationSupported(
- config, supportedFormats);
+ config, supportedFormats, devCfg);
}
protected:
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index 1ed8ed8..ca0c9d6 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -22,7 +22,6 @@
package android.hardware.camera.metadata@3.3;
-/* Include definitions from all prior minor HAL metadata revisions */
import android.hardware.camera.metadata@3.2;
/**
diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal
index bb630f1..30c3217 100644
--- a/camera/metadata/3.4/types.hal
+++ b/camera/metadata/3.4/types.hal
@@ -22,7 +22,6 @@
package android.hardware.camera.metadata@3.4;
-/* Include definitions from all prior minor HAL metadata revisions */
import android.hardware.camera.metadata@3.2;
import android.hardware.camera.metadata@3.3;
@@ -213,8 +212,10 @@
= 0x4,
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RAW
= 0x5,
- ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END
+ ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_LOW_LATENCY_SNAPSHOT
= 0x6,
+ ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END
+ = 0x7,
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VENDOR_START
= 0x18,
};
diff --git a/camera/provider/2.4/default/OWNERS b/camera/provider/2.4/default/OWNERS
index 369b204..f48a95c 100644
--- a/camera/provider/2.4/default/OWNERS
+++ b/camera/provider/2.4/default/OWNERS
@@ -1,7 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-jchowdhary@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
diff --git a/camera/provider/2.4/vts/OWNERS b/camera/provider/2.4/vts/OWNERS
index 003fe71..b8f6b04 100644
--- a/camera/provider/2.4/vts/OWNERS
+++ b/camera/provider/2.4/vts/OWNERS
@@ -1,10 +1,5 @@
# Camera team
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
# VTS team
yim@google.com
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 3949346..d77bb0e 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -782,6 +782,8 @@
void verifySessionReconfigurationQuery(sp<device::V3_5::ICameraDeviceSession> session3_5,
camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
+ bool isDepthOnly(camera_metadata_t* staticMeta);
+
static Status getAvailableOutputStreams(camera_metadata_t *staticMeta,
std::vector<AvailableStream> &outputStreams,
const AvailableStream *threshold = nullptr);
@@ -793,6 +795,10 @@
std::unordered_set<std::string> *physicalIds/*out*/);
static Status getSupportedKeys(camera_metadata_t *staticMeta,
uint32_t tagId, std::unordered_set<int32_t> *requestIDs/*out*/);
+ static void fillOutputStreams(camera_metadata_ro_entry_t* entry,
+ std::vector<AvailableStream>& outputStreams,
+ const AvailableStream *threshold = nullptr,
+ const int32_t availableConfigOutputTag = 0u);
static void constructFilteredSettings(const sp<ICameraDeviceSession>& session,
const std::unordered_set<int32_t>& availableKeys, RequestTemplate reqTemplate,
android::hardware::camera::common::V1_0::helper::CameraMetadata* defaultSettings/*out*/,
@@ -2845,14 +2851,24 @@
uint32_t streamConfigCounter = 0;
for (auto& it : outputStreams) {
V3_2::Stream stream3_2;
- bool isJpeg = static_cast<PixelFormat>(it.format) == PixelFormat::BLOB;
+ V3_2::DataspaceFlags dataspaceFlag = 0;
+ switch (static_cast<PixelFormat>(it.format)) {
+ case PixelFormat::BLOB:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
+ break;
+ case PixelFormat::Y16:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
+ break;
+ default:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
+ }
stream3_2 = {streamId,
StreamType::OUTPUT,
static_cast<uint32_t>(it.width),
static_cast<uint32_t>(it.height),
static_cast<PixelFormat>(it.format),
GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
- (isJpeg) ? static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF) : 0,
+ dataspaceFlag,
StreamRotation::ROTATION_0};
::android::hardware::hidl_vec<V3_2::Stream> streams3_2 = {stream3_2};
::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
@@ -3415,6 +3431,14 @@
castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5);
castDevice(cameraDevice, deviceVersion, &cameraDevice3_5);
+ // Check if camera support depth only
+ if (isDepthOnly(staticMeta)) {
+ free_camera_metadata(staticMeta);
+ ret = session->close();
+ ASSERT_TRUE(ret.isOk());
+ continue;
+ }
+
outputBlobStreams.clear();
ASSERT_EQ(Status::OK,
getAvailableOutputStreams(staticMeta, outputBlobStreams,
@@ -3735,6 +3759,14 @@
castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5);
castDevice(cameraDevice, deviceVersion, &cameraDevice3_5);
+ // Check if camera support depth only
+ if (isDepthOnly(staticMeta)) {
+ free_camera_metadata(staticMeta);
+ ret = session->close();
+ ASSERT_TRUE(ret.isOk());
+ continue;
+ }
+
outputBlobStreams.clear();
ASSERT_EQ(Status::OK,
getAvailableOutputStreams(staticMeta, outputBlobStreams,
@@ -4723,38 +4755,56 @@
Status CameraHidlTest::getAvailableOutputStreams(camera_metadata_t *staticMeta,
std::vector<AvailableStream> &outputStreams,
const AvailableStream *threshold) {
+ AvailableStream depthPreviewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+ static_cast<int32_t>(PixelFormat::Y16)};
if (nullptr == staticMeta) {
return Status::ILLEGAL_ARGUMENT;
}
- camera_metadata_ro_entry entry;
- int rc = find_camera_metadata_ro_entry(staticMeta,
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
- if ((0 != rc) || (0 != (entry.count % 4))) {
+ camera_metadata_ro_entry scalarEntry;
+ camera_metadata_ro_entry depthEntry;
+ int foundScalar = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &scalarEntry);
+ int foundDepth = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, &depthEntry);
+ if ((0 != foundScalar || (0 != (scalarEntry.count % 4))) &&
+ (0 != foundDepth || (0 != (depthEntry.count % 4)))) {
return Status::ILLEGAL_ARGUMENT;
}
- for (size_t i = 0; i < entry.count; i+=4) {
- if (ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT ==
- entry.data.i32[i + 3]) {
+ if(foundScalar == 0 && (0 == (scalarEntry.count % 4))) {
+ fillOutputStreams(&scalarEntry, outputStreams, threshold,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
+ }
+
+ if(foundDepth == 0 && (0 == (depthEntry.count % 4))) {
+ fillOutputStreams(&depthEntry, outputStreams, &depthPreviewThreshold,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT);
+ }
+
+ return Status::OK;
+}
+
+void CameraHidlTest::fillOutputStreams(camera_metadata_ro_entry_t* entry,
+ std::vector<AvailableStream>& outputStreams, const AvailableStream* threshold,
+ const int32_t availableConfigOutputTag) {
+ for (size_t i = 0; i < entry->count; i+=4) {
+ if (availableConfigOutputTag == entry->data.i32[i + 3]) {
if(nullptr == threshold) {
- AvailableStream s = {entry.data.i32[i+1],
- entry.data.i32[i+2], entry.data.i32[i]};
+ AvailableStream s = {entry->data.i32[i+1],
+ entry->data.i32[i+2], entry->data.i32[i]};
outputStreams.push_back(s);
} else {
- if ((threshold->format == entry.data.i32[i]) &&
- (threshold->width >= entry.data.i32[i+1]) &&
- (threshold->height >= entry.data.i32[i+2])) {
- AvailableStream s = {entry.data.i32[i+1],
- entry.data.i32[i+2], threshold->format};
+ if ((threshold->format == entry->data.i32[i]) &&
+ (threshold->width >= entry->data.i32[i+1]) &&
+ (threshold->height >= entry->data.i32[i+2])) {
+ AvailableStream s = {entry->data.i32[i+1],
+ entry->data.i32[i+2], threshold->format};
outputStreams.push_back(s);
}
}
}
-
}
-
- return Status::OK;
}
// Get max jpeg buffer size in android.jpeg.maxSize
@@ -5226,6 +5276,37 @@
ASSERT_TRUE(ret.isOk());
}
+bool CameraHidlTest::isDepthOnly(camera_metadata_t* staticMeta) {
+ camera_metadata_ro_entry scalarEntry;
+ camera_metadata_ro_entry depthEntry;
+
+ int rc = find_camera_metadata_ro_entry(
+ staticMeta, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &scalarEntry);
+ if (rc == 0) {
+ for (uint32_t i = 0; i < scalarEntry.count; i++) {
+ if (scalarEntry.data.u8[i] == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
+ return false;
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < scalarEntry.count; i++) {
+ if (scalarEntry.data.u8[i] == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) {
+
+ rc = find_camera_metadata_ro_entry(
+ staticMeta, ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, &depthEntry);
+ size_t i = 0;
+ if (rc == 0 && depthEntry.data.i32[i] == static_cast<int32_t>(PixelFormat::Y16)) {
+ // only Depth16 format is supported now
+ return true;
+ }
+ break;
+ }
+ }
+
+ return false;
+}
+
// Open a device session and configure a preview stream.
void CameraHidlTest::configurePreviewStream(const std::string &name, int32_t deviceVersion,
sp<ICameraProvider> provider,
@@ -5316,11 +5397,20 @@
ASSERT_EQ(Status::OK, rc);
ASSERT_FALSE(outputPreviewStreams.empty());
+ V3_2::DataspaceFlags dataspaceFlag = 0;
+ switch (static_cast<PixelFormat>(outputPreviewStreams[0].format)) {
+ case PixelFormat::Y16:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
+ break;
+ default:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
+ }
+
V3_2::Stream stream3_2 = {0, StreamType::OUTPUT,
static_cast<uint32_t> (outputPreviewStreams[0].width),
static_cast<uint32_t> (outputPreviewStreams[0].height),
static_cast<PixelFormat> (outputPreviewStreams[0].format),
- GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0, StreamRotation::ROTATION_0};
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, dataspaceFlag, StreamRotation::ROTATION_0};
::android::hardware::hidl_vec<V3_2::Stream> streams3_2 = {stream3_2};
::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
diff --git a/camera/provider/2.5/default/OWNERS b/camera/provider/2.5/default/OWNERS
index 369b204..f48a95c 100644
--- a/camera/provider/2.5/default/OWNERS
+++ b/camera/provider/2.5/default/OWNERS
@@ -1,7 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-jchowdhary@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av:/camera/OWNERS
diff --git a/current.txt b/current.txt
index 4ad47e1..f170705 100644
--- a/current.txt
+++ b/current.txt
@@ -390,15 +390,16 @@
684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
f8a19622cb0cc890913b1ef3e32b675ffb26089a09e02fef4056ebad324d2b5d android.hardware.camera.device@3.4::types
291638a1b6d4e63283e9e722ab5049d9351717ffa2b66162124f84d1aa7c2835 android.hardware.camera.metadata@3.2::types
-a31142da4cc87ad50e4e981d12291d4decbb432fcb00f175f0ca904d0fcdbe5b android.hardware.camera.metadata@3.3::types
+23780340c686ee86986aa5a9755c2d8566224fed177bbb22a5ebf06be574b60c android.hardware.camera.metadata@3.3::types
da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
21165b8e30c4b2d52980e4728f661420adc16e38bbe73476c06b2085be908f4c android.hardware.gnss@1.0::IGnssCallback
d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback
+7c7721c0f773fcf422b71a4f558545e9e36acc973e58ca51e5bd53905cf46bc0 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
d4fea995378bb4f421b4e24ccf68cad2734ab07fe4f874a126ba558b99df5766 android.hardware.graphics.composer@2.1::IComposerClient
b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
417ab60fe1ef786778047e4486f3d868ebce570d91addd8fe4251515213072de android.hardware.neuralnetworks@1.0::types
-e22e8135d061d0e9c4c1a70c25c19fdba10f4d3cda9795ef25b6392fc520317c android.hardware.neuralnetworks@1.1::types
+ec8aa14fe9b03f2b3fb9845346a4005b6d098ebe2277b2564f73a548a0fd14a7 android.hardware.neuralnetworks@1.1::types
1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse
ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types
1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
@@ -419,7 +420,7 @@
9471b12b1c255bb530695720bc4174bd74987b75b1f820854af8944bc8c215c9 android.hardware.audio@5.0::IStreamOut
1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback
83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types
-894af04bebfe7da5b6791eefeb6eb3627da63d5efea735f16876d11d8ca4f61d android.hardware.audio.common@5.0::types
+07d17800b298331e90d4ea5d8ba19a1ae3fe9c1dbff08d9f75fd3ade09496d67 android.hardware.audio.common@5.0::types
f269297866765b95ddd1825676cc8a772f0c7c9863286df596fc302781a42ff5 android.hardware.audio.effect@5.0::IAcousticEchoCancelerEffect
fa187b602d8939644ef708ed7627f2e3deac97899a4bda1de07f2ff126abe243 android.hardware.audio.effect@5.0::IAutomaticGainControlEffect
e1bf864ccb8458c0da1dcc74a2e748b1dca8ac360df590591cf82d98292d7981 android.hardware.audio.effect@5.0::IBassBoostEffect
@@ -435,9 +436,9 @@
443659bb9e27221e5da0d16c7a0ecb2dc3a9a03acc8a0b2196b47c50735e2d2e android.hardware.audio.effect@5.0::IVirtualizerEffect
78fed26a781cdca1b3bcb37520bff705d7764ee81db9cfd37014953c7ad2596e android.hardware.audio.effect@5.0::IVisualizerEffect
6385b6accab8a544e2ee54ba7bf5aa55dff6153bcedd80fdaae16fe9e0be7050 android.hardware.audio.effect@5.0::types
-baf5a0cbf357035394be02d87334890228338fae715f7ab06e2f0e7d05abe656 android.hardware.biometrics.face@1.0::IBiometricsFace
-6cbf288d6e6a9f6f0c09d1cde66318aa5b6a8c525778a61ccaedddb090f5e9cb android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback
-ef5d339413d0c94a5b58baafbe3e4bccfd9ed2e7328fbbb5c25471c79923ed2f android.hardware.biometrics.face@1.0::types
+e18ff318f3fc43db37f554696dc4e551abb9b119bde53950f73e28ce33a97a40 android.hardware.biometrics.face@1.0::IBiometricsFace
+b6e55d7795bbafd011fb95a3b6d3954bf66c349e14cf107f3b72032ce3ceb448 android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback
+95aa2f59e29e2f84d8e84320ace9b6682b426a16e897b4bd241375cbee0e07f3 android.hardware.biometrics.face@1.0::types
ecedc58dbcdb13503c19c0ab160ac1dd0530bb1471164149282dd1463c684185 android.hardware.bluetooth.audio@2.0::IBluetoothAudioPort
fb9c40e4deab40be5476477078fe3d8a4a4495fd9deef4321878d169d675c633 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvider
f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory
@@ -446,7 +447,7 @@
06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback
08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession
a848f7cb3cb3d080cf175bf08412322bfddb535168253796cdf777afdbf05b38 android.hardware.camera.device@3.5::types
-74ec7732fdacb22292c907b49f8f933510851ea1b3ed195c4dcdff35a20387f5 android.hardware.camera.metadata@3.4::types
+f727d5f350f55a6d3354aad2feb64e43200de77c10d9d642465566bc260bb8ec android.hardware.camera.metadata@3.4::types
0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider
f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardware.camera.provider@2.5::types
44c88954b3c201b26f64fcdb6f278024ab3aae864a9e1ec70e8a74274ae9d6aa android.hardware.cas@1.1::ICas
@@ -463,23 +464,27 @@
7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss
2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback
1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil
-6e2f9a44375a0ae0b49ca7d711cb88945189d398535078408269e1e85889061d android.hardware.gnss@2.0::IGnss
-d815623a6d1ba4abf21248b84eca70a2bfab03058a88b68a29c063ce8aee6b5c android.hardware.gnss@2.0::IGnssCallback
+4deafcdcffa2d002119e7f58810b767a84666e76475aae68e757ec2845d9756d android.hardware.gnss@2.0::IGnss
+db6bdf6dfc5edf6c85d2944976db899227abb51079c893874353c322342c50b6 android.hardware.gnss@2.0::IGnssBatching
+1f89392f1ebb693d8fa6f50324b1635fc79fab246d31900e63998e1b0e17511c android.hardware.gnss@2.0::IGnssBatchingCallback
+b11a5e4a1602d3f408716b6fe2c578a79f060d571aad8e828f9a4426d161fbcf android.hardware.gnss@2.0::IGnssCallback
ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration
+b670bae2ab8517336290532e364502b4db9120340d75474ccc8442b1b15d6ab7 android.hardware.gnss@2.0::IGnssDebug
c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement
-089338944c45f66f25ba4ee958c161c42fefeb73ec60e4451f3535a1b3fd10c7 android.hardware.gnss@2.0::IGnssMeasurementCallback
-9e66234e65bcde75733d75d8b5d5cc094c2a5e14b074a25cd3f9ad141dc56f60 android.hardware.gnss@2.0::types
-50623a69a88b1c8a05738e4af7d5f78e905f415ccb0e84c99d0a71ea182e9393 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections
+15e09903748857f4beb5f485784606931fa5a6277cd070baa6d584df485b7948 android.hardware.gnss@2.0::IGnssMeasurementCallback
+a49c973f21ddf41bc402de55d7c8dffacf4dce06b0bbca4f5ffd3b09a471317e android.hardware.gnss@2.0::types
+d4cc8d91930d5a1a62deb0d97d398510a115ce3ede2d2978738651b9d01b11c3 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections
+3eec9763db9b101644f14175b77c9954047445a468e9c743fd402d472d4aa97e android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrectionsCallback
6ef12cd95df73f8f80c25eb035d98ca4594f9cee571fdabea838a0b6016dd908 android.hardware.gnss.measurement_corrections@1.0::types
0d278956d7fc6fdf9ca9c42962ff2d73967bbb1c9f0b3e0b58d71b7095c286bc android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl
0d99e34500cfc2d40b684cb4dea7ebd89d4aff9f5315ed36b33442a7a88c138c android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControlCallback
6b2d8dfa3db505c34a3a19082d8737c86bd859ec00f0e6c5fd19cce3c1ef95d1 android.hardware.graphics.allocator@3.0::IAllocator
-2a81d3132df91614a30ca45dfe088d67ddbb30240ab8c25feb6b8110d7ec3800 android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer
+eb3bcf4e8afacc72fd09821920f277fbbe8b9837513c1f5549fb42588580cbe4 android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer
b826892686850a9cf2b60ca5845db7185c2196ea4dd765cd80cd163169678a78 android.hardware.graphics.bufferqueue@2.0::IProducerListener
01c6398c90fc6be0640810e2c5d8a4863b457280132bb3f97dd5682e19632b62 android.hardware.graphics.bufferqueue@2.0::types
7a2d64095252f85781b2d521f4f11d04ce774544feececcec2088c568656e93c android.hardware.graphics.common@1.2::types
3dff04a36b86660b5807414587e530bb0c294ed56fdff06f8915ba0a9b73f974 android.hardware.graphics.composer@2.3::IComposer
-daa44e83d7709bf1c9e0bd9a6b552feff496fd14574a9461ee93c21980fc5b15 android.hardware.graphics.composer@2.3::IComposerClient
+54bc1dc874f8bc0781767786075dafd33a0796c1eea7d2317231b8929280e946 android.hardware.graphics.composer@2.3::IComposerClient
5c8bf8e1af9efe225a4661db8c08ff1b7e13fdc8ed49f35291bd0b6c9436b8f2 android.hardware.graphics.mapper@3.0::IMapper
7183d9d9acfa41a61a64bdfed548e98299265a7bb1821a3ed204173b5c2cfd4a android.hardware.graphics.mapper@3.0::types
c3f831a66d5815baf74f5b82fe79cf099542ddae4dfab3f388e1d41828e794fc android.hardware.health.storage@1.0::IGarbageCollectCallback
@@ -492,22 +497,22 @@
aee53b2865b4f7939fb3df6fae758d9750c14f93dd454b479fc74aa7978fda4f android.hardware.media.bufferpool@2.0::IConnection
0bf3758eeeb05767830ea87041214be80968c4679fb73577ac5b3091841ee71f android.hardware.media.bufferpool@2.0::IObserver
82255e252ae215382473ad2e5ac7a2814a439a24f0092551aad7a2f89c6e9546 android.hardware.media.bufferpool@2.0::types
-277161ea99236a0858e9fcc021c357db03be2de500acf5701d125e73e3e8071a android.hardware.media.c2@1.0::IComponent
+7faa207e2507c6a2617e5ec2554b83383ebe392b6e627dddf2e3b0eae5715ba8 android.hardware.media.c2@1.0::IComponent
389d06e4a4ecf60f828a260045b0c327a5ae883ee0856a3c054556dd22b1f450 android.hardware.media.c2@1.0::IComponentInterface
5ee0c02265c5505ade189796bef46697df4e0563e3544bb0c934855b34694b07 android.hardware.media.c2@1.0::IComponentListener
43d70bcdc63b3d042bac3c3297f5d941dfabbd08f3ceb96b6016cc14f6e34ba3 android.hardware.media.c2@1.0::IComponentStore
d36f747f9c9a8f2f21db2f8323c2d755dd08b34ce813932d7339979f7d490dab android.hardware.media.c2@1.0::IConfigurable
-cd2bd9f424515aeb0c2b91f3bb879797defb5b846b8660784b68d225285bcdff android.hardware.media.c2@1.0::IInputSink
-c3dfaa1fcd452c6cfc26d8dcbb67b71b08a1fe6dad5f87427e93d11a95372b05 android.hardware.media.c2@1.0::IInputSurface
+21aa259585caaa27b6470ebcd8509aabde0ef5d039160aa6425d589cb787488b android.hardware.media.c2@1.0::IInputSink
+b9422a9aca84df1ff9623dc12c0562abce97716e28d63a965f2bfb88f9ad9607 android.hardware.media.c2@1.0::IInputSurface
0a786a19e6753f9774a7ca7781c2a2edfe5c0b5fa112355dfa0e50ebedeb08b9 android.hardware.media.c2@1.0::IInputSurfaceConnection
4cb139f729c29d8d6f4ecdab149c4feb571dad8a06e56cd57fcb52e70208bab4 android.hardware.media.c2@1.0::types
4880af120fc1640225abdc2c60bda6d79617d73484d5124913c7278af3b11e2d android.hardware.neuralnetworks@1.2::IBurstCallback
19877e466ad8c6ed42b38050b77bd010cf7800ff365fdc8574f45bbfda03a758 android.hardware.neuralnetworks@1.2::IBurstContext
-96249c852dabeefa3a9496ecdfc44681a071c665bfbf88527bf775c88bf1ab1b android.hardware.neuralnetworks@1.2::IDevice
+363821d1b71147b896a08e2a570946db9b9d46f90d9f91b085bd8d3013a2b4d5 android.hardware.neuralnetworks@1.2::IDevice
92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback
-83885d366f22ada42c00d8854f0b7e7ba4cf73ddf80bb0d8e168ce132cec57ea android.hardware.neuralnetworks@1.2::IPreparedModel
+36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel
e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback
-896d1827541d620996720a79c6476edb902a58d515bf908f67a5bdef4d2c318c android.hardware.neuralnetworks@1.2::types
+39a6d7cf9bc7290bd90739e971ccad5f35f5cc0faea4a417b59f22c9ca9f1f2a android.hardware.neuralnetworks@1.2::types
cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc
abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types
4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats
@@ -539,7 +544,8 @@
61bc302e7c974c59b25898c585c6e9685e8a81021b1bed3eedf5224198f2785a android.hardware.usb@1.2::IUsb
46996cd2a1c66261a75a1f6ecada77eeb5861eb264fa39b996548fe0a7f22dd3 android.hardware.usb@1.2::IUsbCallback
3bbaa8cbc5d6b1da21f5509b2b641e05fc7eeca1354751eb1bb3cf37f89aa32f android.hardware.usb@1.2::types
-92c1a726c80970d623b891f7c2f9a989a40a15ee1244092b49f4eb6adcdce4e9 android.hardware.vibrator@1.3::IVibrator
+0f7ff73793548d5154014059b7e0fe9ef6355d32218ace157954d02055f5248b android.hardware.vibrator@1.3::IVibrator
+2e313dc27a1327a29862ab3e085917f75c9e996f7c8df5a0ce37b9a0ed076b80 android.hardware.vibrator@1.3::types
f19832856a3f53ced5ef91d3cc630a57fb7f4d4ce15f364dbed09099b89f6830 android.hardware.wifi@1.3::IWifi
7c6799c19bfdb3dec016b751556fe246cf7d37191ee7bb82a0091ab9fbf6f2fb android.hardware.wifi@1.3::IWifiChip
3bef30e8b61ab050c0f6fd26572712be5ebb7707d624c9aa6c74bbb9d6a5b4a9 android.hardware.wifi@1.3::IWifiStaIface
diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp
index 067b5e4..252ebb9 100644
--- a/drm/1.2/vts/functional/drm_hal_test.cpp
+++ b/drm/1.2/vts/functional/drm_hal_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "drm_hal_clearkey_test@1.2"
+#define LOG_TAG "drm_hal_test@1.2"
#include <gtest/gtest.h>
#include <hidl/HidlSupport.h>
@@ -41,8 +41,8 @@
static const char* const kVideoMp4 = "video/mp4";
static const char* const kBadMime = "video/unknown";
static const char* const kDrmErrorTestKey = "drmErrorTest";
-static const char* const kDrmErrorGeneric = "";
-static const char* const kResourceContentionValue = "resourceContention";
+static const char* const kDrmErrorInvalidState = "invalidState";
+static const char* const kDrmErrorResourceContention = "resourceContention";
static const SecurityLevel kSwSecureCrypto = SecurityLevel::SW_SECURE_CRYPTO;
/**
@@ -180,19 +180,36 @@
}
/**
- * Test clearkey plugin offline key support
+ * Test drm plugin offline key support
*/
TEST_P(DrmHalTest, OfflineLicenseTest) {
auto sessionId = openSession();
hidl_vec<uint8_t> keySetId = loadKeys(sessionId, KeyType::OFFLINE);
- auto res = drmPlugin->getOfflineLicenseKeySetIds(checkKeySetIds<Status::OK, 1u>);
+ auto res = drmPlugin->getOfflineLicenseKeySetIds(
+ [&](Status status, const hidl_vec<KeySetId>& keySetIds) {
+ bool found = false;
+ EXPECT_EQ(Status::OK, status);
+ for (KeySetId keySetId2: keySetIds) {
+ if (keySetId == keySetId2) {
+ found = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(found) << "keySetId not found";
+ });
EXPECT_OK(res);
Status err = drmPlugin->removeOfflineLicense(keySetId);
EXPECT_EQ(Status::OK, err);
- res = drmPlugin->getOfflineLicenseKeySetIds(checkKeySetIds<Status::OK, 0u>);
+ res = drmPlugin->getOfflineLicenseKeySetIds(
+ [&](Status status, const hidl_vec<KeySetId>& keySetIds) {
+ EXPECT_EQ(Status::OK, status);
+ for (KeySetId keySetId2: keySetIds) {
+ EXPECT_NE(keySetId, keySetId2);
+ }
+ });
EXPECT_OK(res);
err = drmPlugin->removeOfflineLicense(keySetId);
@@ -202,7 +219,7 @@
}
/**
- * Test clearkey plugin offline key state
+ * Test drm plugin offline key state
*/
TEST_P(DrmHalTest, OfflineLicenseStateTest) {
auto sessionId = openSession();
@@ -380,7 +397,7 @@
* Test resource contention during attempt to generate key request
*/
TEST_P(DrmHalClearkeyTest, GetKeyRequestResourceContention) {
- Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kResourceContentionValue);
+ Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorResourceContention);
EXPECT_EQ(Status::OK, status);
auto sessionId = openSession();
hidl_vec<uint8_t> initData;
@@ -403,7 +420,7 @@
TEST_P(DrmHalClearkeyTest, OfflineLicenseInvalidState) {
auto sessionId = openSession();
hidl_vec<uint8_t> keySetId = loadKeys(sessionId, KeyType::OFFLINE);
- Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorGeneric);
+ Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorInvalidState);
EXPECT_EQ(Status::OK, status);
// everything should start failing
@@ -426,7 +443,7 @@
auto res = drmPlugin->setListener(listener);
EXPECT_OK(res);
- Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorGeneric);
+ Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorInvalidState);
EXPECT_EQ(Status::OK, status);
auto sessionId = openSession();
diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp
index c01ec55..6cfd346 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -12,8 +12,11 @@
"IAGnssCallback.hal",
"IAGnssRil.hal",
"IGnss.hal",
+ "IGnssBatching.hal",
+ "IGnssBatchingCallback.hal",
"IGnssCallback.hal",
"IGnssConfiguration.hal",
+ "IGnssDebug.hal",
"IGnssMeasurement.hal",
"IGnssMeasurementCallback.hal",
],
diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal
index 2c149b7..f19f8d0 100644
--- a/gnss/2.0/IGnss.hal
+++ b/gnss/2.0/IGnss.hal
@@ -23,9 +23,11 @@
import GnssLocation;
import IGnssCallback;
import IGnssConfiguration;
+import IGnssDebug;
import IGnssMeasurement;
import IAGnss;
import IAGnssRil;
+import IGnssBatching;
/**
* Represents the standard GNSS (Global Navigation Satellite System) interface.
@@ -55,6 +57,13 @@
getExtensionGnssConfiguration_2_0() generates (IGnssConfiguration gnssConfigurationIface);
/**
+ * This method returns the IGnssDebug interface.
+ *
+ * @return gnssDebugIface Handle to the IGnssDebug interface.
+ */
+ getExtensionGnssDebug_2_0() generates (IGnssDebug gnssDebugIface);
+
+ /**
* This method returns the IAGnss Interface.
*
* The getExtensionAGnss() must return nullptr as the @1.0::IAGnss interface is
@@ -97,6 +106,13 @@
getExtensionVisibilityControl() generates (IGnssVisibilityControl visibilityControlIface);
/**
+ * This method returns the IGnssBatching interface.
+ *
+ * @return batchingIface Handle to the IGnssBatching interface.
+ */
+ getExtensionGnssBatching_2_0() generates (IGnssBatching batchingIface);
+
+ /**
* Injects current location from the best available location provider.
*
* Unlike injectLocation, this method may inject a recent GNSS location from the HAL
diff --git a/gnss/2.0/IGnssBatching.hal b/gnss/2.0/IGnssBatching.hal
new file mode 100644
index 0000000..961fa69
--- /dev/null
+++ b/gnss/2.0/IGnssBatching.hal
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 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.gnss@2.0;
+
+import @1.0::IGnssBatching;
+import IGnssBatchingCallback;
+
+/**
+ * Extended interface for GNSS Batching support.
+ *
+ * If this interface is supported, this batching request must be able to run in
+ * parallel with, or without, non-batched location requested by the
+ * IGnss start() & stop() - i.e. both requests must be handled independently,
+ * and not interfere with each other.
+ *
+ * For example, if a 1Hz continuous output is underway on the IGnssCallback,
+ * due to an IGnss start() operation,
+ * and then a IGnssBatching start() is called for a location every 10
+ * seconds, the newly added batching request must not disrupt the 1Hz
+ * continuous location output on the IGnssCallback.
+ *
+ * As with GNSS Location outputs, source of location must be GNSS satellite
+ * measurements, optionally using interial and baro sensors to improve
+ * relative motion filtering. No additional absolute positioning information,
+ * such as WiFi derived location, may be mixed with the GNSS information.
+ */
+interface IGnssBatching extends @1.0::IGnssBatching {
+ /**
+ * Opens the interface and provides the callback routines
+ * to the implementation of this interface.
+ *
+ * @param callback Callback interface for IGnssBatching.
+ *
+ * @return success Returns true on success.
+ */
+ init_2_0(IGnssBatchingCallback callback) generates (bool success);
+};
\ No newline at end of file
diff --git a/gnss/2.0/IGnssBatchingCallback.hal b/gnss/2.0/IGnssBatchingCallback.hal
new file mode 100644
index 0000000..4f8b4ec
--- /dev/null
+++ b/gnss/2.0/IGnssBatchingCallback.hal
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 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.gnss@2.0;
+
+/** The callback interface to report measurements from the HAL. */
+interface IGnssBatchingCallback {
+ /**
+ * Called when a batch of locations is output, by various means, including
+ * a flush request, as well as the buffer becoming full (if appropriate option
+ * is set.)
+ *
+ * All locations returned by this callback must be cleared from the hardware
+ * buffer, such the sequential calls of this callback do not return any
+ * redundant locations. (Same lat/lon, at a new time, is acceptable.)
+ *
+ * The GnssLocation struct in gnss@2.0 is extended to include elapsed realtime
+ * information.
+ *
+ * @param locations GNSS Location information from HAL.
+ */
+ gnssLocationBatchCb(vec<GnssLocation> locations);
+};
diff --git a/gnss/2.0/IGnssCallback.hal b/gnss/2.0/IGnssCallback.hal
index 7924b64..a96fd6c 100644
--- a/gnss/2.0/IGnssCallback.hal
+++ b/gnss/2.0/IGnssCallback.hal
@@ -19,9 +19,10 @@
import @1.0::IGnssCallback;
import @1.1::IGnssCallback;
import GnssLocation;
+import GnssConstellationType;
/**
- * The interface is required for the HAL to communicate certain information
+ * This interface is required for the HAL to communicate certain information
* like status and location info back to the platform, the platform implements
* the interfaces and passes a handle to the HAL.
*/
@@ -29,17 +30,36 @@
/** Flags for the gnssSetCapabilities callback. */
@export(name="", value_prefix="GPS_CAPABILITY_")
- enum Capabilities : @1.0::IGnssCallback.Capabilities {
- /** GNSS supports line-of-sight satellite identification measurement Corrections */
- MEASUREMENT_CORRECTIONS_LOS_SATS = 1 << 8,
- /** GNSS supports per satellite excess-path-length measurement Corrections */
- MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH = 1 << 9,
- /** GNSS supports reflecting planes measurement Corrections */
- MEASUREMENT_CORRECTIONS_REFLECTING_PLANE = 1 << 10
+ enum Capabilities : uint32_t {
+ /**
+ * GNSS HAL schedules fixes for RECURRENCE_PERIODIC mode.
+ * If this is not set, then the framework will use 1000ms for
+ * minInterval and must call start() and stop() to schedule the GNSS.
+ */
+ SCHEDULING = 1 << 0,
+ /** GNSS supports MS-Based AGNSS mode */
+ MSB = 1 << 1,
+ /** GNSS supports MS-Assisted AGNSS mode */
+ MSA = 1 << 2,
+ /** GNSS supports single-shot fixes */
+ SINGLE_SHOT = 1 << 3,
+ /** GNSS supports on demand time injection */
+ ON_DEMAND_TIME = 1 << 4,
+ /**
+ * Values for the flags removed from IGnssCallback.hal@1.0 Capabilities
+ * enum are marked as reserved and not reused here to avoid confusion.
+ */
+ RESERVED_1 = 1 << 5,
+ RESERVED_2 = 1 << 6,
+ RESERVED_3 = 1 << 7,
+ /** GNSS supports low power mode */
+ LOW_POWER_MODE = 1 << 8,
+ /** GNSS supports blacklisting satellites */
+ SATELLITE_BLACKLIST = 1 << 9
};
/**
- * Callback to inform framework of the GNSS engine's capabilities.
+ * Callback to inform framework of the GNSS HAL implementation's capabilities.
*
* @param capabilities Capability parameter is a bit field of the Capabilities enum.
*/
@@ -75,4 +95,26 @@
* during-call to E911, or up to 5 minutes after end-of-call or text to E911).
*/
gnssRequestLocationCb_2_0(bool independentFromGnss, bool isUserEmergency);
-};
\ No newline at end of file
+
+ /** Extends a GnssSvInfo, replacing the GnssConstellationType. */
+ struct GnssSvInfo {
+ /**
+ * GNSS satellite information for a single satellite and frequency.
+ *
+ * In this version of the HAL, the field 'constellation' in the v1_0 struct is deprecated,
+ * and is no longer used by the framework. The constellation type is instead reported in
+ * @2.0::IGnssCallback.GnssSvInfo.constellation.
+ */
+ @1.0::IGnssCallback.GnssSvInfo v1_0;
+
+ /** Defines the constellation of the given SV. */
+ GnssConstellationType constellation;
+ };
+
+ /**
+ * Callback for the HAL to pass a vector of GnssSvInfo back to the client.
+ *
+ * @param svInfo SV status information from HAL.
+ */
+ gnssSvStatusCb_2_0(vec<GnssSvInfo> svInfoList);
+};
diff --git a/gnss/2.0/IGnssDebug.hal b/gnss/2.0/IGnssDebug.hal
new file mode 100644
index 0000000..a3138ba
--- /dev/null
+++ b/gnss/2.0/IGnssDebug.hal
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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.gnss@2.0;
+
+import @1.0::IGnssDebug;
+
+/** Extended interface for DEBUG support. */
+interface IGnssDebug extends @1.0::IGnssDebug {
+
+ /** Extending SatelliteData, replacing the GnssConstellationType. */
+ struct SatelliteData {
+ /**
+ * GNSS Satellite info.
+ *
+ * In this version of the HAL, the field 'constellation' in the v1_0 struct is deprecated,
+ * and is no longer used by the framework. The constellation type is instead reported in
+ * @2.0::IGnssDebug.SatelliteData.constellation.
+ */
+ @1.0::IGnssDebug.SatelliteData v1_0;
+
+ /** Defines the constellation type of the given SV. */
+ GnssConstellationType constellation;
+ };
+
+ /**
+ * Provides a set of debug information that is filled by the GNSS chipset when the method
+ * getDebugData() is invoked.
+ */
+ struct DebugData {
+ /** Current best known position. */
+ @1.0::IGnssDebug.PositionDebug position;
+
+ /** Current best know time estimate. */
+ @1.0::IGnssDebug.TimeDebug time;
+
+ /**
+ * Provides a list of the available satellite data, for all
+ * satellites and constellations the device can track,
+ * including GnssConstellationType UNKNOWN.
+ */
+ vec<SatelliteData> satelliteDataArray;
+ };
+
+ /**
+ * This methods requests position, time and satellite ephemeris debug information from the HAL.
+ *
+ * @return ret debugData information from GNSS Hal that contains the current best known
+ * position, best known time estimate and a complete list of constellations that the device can
+ * track.
+ */
+ getDebugData_2_0() generates (DebugData debugData);
+};
diff --git a/gnss/2.0/IGnssMeasurementCallback.hal b/gnss/2.0/IGnssMeasurementCallback.hal
index d5dc038..e055f7a 100644
--- a/gnss/2.0/IGnssMeasurementCallback.hal
+++ b/gnss/2.0/IGnssMeasurementCallback.hal
@@ -19,80 +19,10 @@
import @1.0::IGnssMeasurementCallback;
import @1.1::IGnssMeasurementCallback;
import ElapsedRealtime;
+import GnssConstellationType;
/** The callback interface to report measurements from the HAL. */
interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback {
- /**
- * Enumeration of available values for the GNSS Measurement's code type. Similar to the
- * Attribute field described in RINEX 3.03, e.g., in Tables 4-10, and Table A2 at the RINEX 3.03
- * Update 1 Document.
- */
- enum GnssMeasurementCodeType : uint8_t {
- /** GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA. */
- A = 0,
-
- /** GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB. */
- B = 1,
-
- /**
- * GPS L1 C/A, GPS L2 C/A, GLONASS G1 C/A, GLONASS G2 C/A, GALILEO E1C, GALILEO E6C, SBAS
- * L1 C/A, QZSS L1 C/A, IRNSS L5C.
- */
- C = 2,
-
- /**
- * GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, GALILEO E5a+b I, SBAS L5 I, QZSS L5
- * I, BDS B1 I, BDS B2 I, BDS B3 I.
- */
- I = 3,
-
- /** GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L), LEX(6) L. */
- L = 4,
-
- /** GPS L1M, GPS L2M. */
- M = 5,
-
- /** GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P. */
- P = 6,
-
- /**
- * GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, GALILEO E5a+b Q, SBAS L5 Q, QZSS L5
- * Q, BDS B1 Q, BDS B2 Q, BDS B3 Q.
- */
- Q = 7,
-
- /** GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M), LEX(6) S. */
- S = 8,
-
- /** GPS L1 Z-tracking, GPS L2 Z-tracking. */
- W = 9,
-
- /**
- * GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), GLONASS G3 (I+Q), GALILEO E1 (B+C), GALILEO
- * E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q), GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS
- * L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q), LEX(6) (S+L), BDS B1 (I+Q), BDS B2 (I+Q), BDS
- * B3 (I+Q), IRNSS L5 (B+C).
- */
- X = 10,
-
- /** GPS L1Y, GPS L2Y. */
- Y = 11,
-
- /** GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF. */
- Z = 12,
-
- /** GPS L1 codeless, GPS L2 codeless. */
- N = 13,
-
- /**
- * Other code type that does not belong to any of the above code types.
- *
- * This code type is used in the case that the above code types do not cover all the code
- * types introduced in a new version of RINEX standard. When this code type is set, the
- * field GnssMeasurement.otherCodeTypeName must specify the new code type.
- */
- OTHER = 255
- };
/**
* Flags indicating the GNSS measurement state.
@@ -436,7 +366,8 @@
};
/**
- * Extends a GNSS Measurement, adding a GnssMeasurementCodeType.
+ * Extends a GNSS Measurement, adding a GnssMeasurementCodeType, a GnssMeasurementState, and
+ * replacing the GnssConstellationType.
*/
struct GnssMeasurement {
/**
@@ -451,6 +382,10 @@
* In this version of the HAL, the field 'state' in the v1_1.v1_0 struct is deprecated, and
* is no longer used by the framework. The satellite sync state is instead reported in
* @2.0::IGnssMeasurementCallback.GnssMeasurement.state.
+ *
+ * In this version of the HAL, the field 'constellation' in the v1_1.v1_0 struct is
+ * deprecated, and is no longer used by the framework. The constellation type is instead
+ * reported in @2.0::IGnssMeasurementCallback.GnssMeasurement.constellation.
*/
@1.1::IGnssMeasurementCallback.GnssMeasurement v1_1;
@@ -458,12 +393,43 @@
* The type of code that is currently being tracked in the GNSS measurement.
*
* For high precision applications the type of code being tracked needs to be considered
- * in-order to properly apply code specific corrections to the psuedorange measurements.
- */
- GnssMeasurementCodeType codeType;
-
- /**
- * The name of the code type when codeType is OTHER.
+ * in-order to properly apply code specific corrections to the pseudorange measurements.
+ *
+ * Value "A" represents GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA.
+ *
+ * Value "B" represents GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB.
+ *
+ * Value "C" represents GPS L1 C/A, GPS L2 C/A, GLONASS G1 C/A, GLONASS G2 C/A, GALILEO E1C,
+ * GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C.
+ *
+ * Value "I" represents GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, GALILEO E5a+b I,
+ * SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I.
+ *
+ * Value "L" represents GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L), LEX(6) L.
+ *
+ * Value "M" represents GPS L1M, GPS L2M.
+ *
+ * Value "N" represents GPS L1 codeless, GPS L2 codeless.
+ *
+ * Value "P" represents GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P.
+ *
+ * Value "Q" represents GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, GALILEO E5a+b Q,
+ * SBAS L5 Q, QZSS L5 Q, BDS B1 Q, BDS B2 Q, BDS B3 Q.
+ *
+ * Value "S" represents GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M), LEX(6) S.
+ *
+ * Value "W" represents GPS L1 Z-tracking, GPS L2 Z-tracking.
+ *
+ * Value "X" represents GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), GLONASS G3 (I+Q),
+ * GALILEO E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q),
+ * GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q),
+ * LEX(6) (S+L), BDS B1 (I+Q), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C).
+ *
+ * Value "Y" represents GPS L1Y, GPS L2Y.
+ *
+ * Value "Z" represents GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF.
+ *
+ * Value "UNKNOWN" represents the GNSS Measurement's code type is unknown.
*
* This is used to specify the observation descriptor defined in GNSS Observation Data File
* Header Section Description in the RINEX standard (Version 3.XX). In RINEX Version 3.03,
@@ -471,7 +437,7 @@
* "A channel"). In the future, if for instance a code "G" was added in the official RINEX
* standard, "G" could be specified here.
*/
- string otherCodeTypeName;
+ string codeType;
/**
* Per satellite sync state. It represents the current sync state for the associated
@@ -482,6 +448,11 @@
* This value is mandatory.
*/
bitfield<GnssMeasurementState> state;
+
+ /**
+ * The constellation type of the GNSS measurement.
+ */
+ GnssConstellationType constellation;
};
/**
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 64187e2..0fcd764 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -25,6 +25,7 @@
"AGnss.cpp",
"AGnssRil.cpp",
"Gnss.cpp",
+ "GnssBatching.cpp",
"GnssMeasurement.cpp",
"GnssMeasurementCorrections.cpp",
"GnssVisibilityControl.cpp",
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index ee6da53..75c2385 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -23,6 +23,7 @@
#include "AGnss.h"
#include "AGnssRil.h"
+#include "GnssBatching.h"
#include "GnssConfiguration.h"
#include "GnssMeasurement.h"
#include "GnssMeasurementCorrections.h"
@@ -236,6 +237,11 @@
return new GnssConfiguration{};
}
+Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
+ // TODO(b/124012850): Implement function.
+ return sp<V2_0::IGnssDebug>{};
+}
+
Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
return new AGnss{};
}
@@ -260,6 +266,10 @@
return new GnssVisibilityControl();
}
+Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
+ return new GnssBatching();
+}
+
Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
ALOGD("Gnss::setCallback_2_0");
if (callback == nullptr) {
@@ -269,8 +279,9 @@
sGnssCallback_2_0 = callback;
- uint32_t capabilities = static_cast<uint32_t>(V1_0::IGnssCallback::Capabilities::MEASUREMENTS);
- auto ret = sGnssCallback_2_0->gnssSetCapabilitesCb(capabilities);
+ using Capabilities = V2_0::IGnssCallback::Capabilities;
+ const auto capabilities = Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
+ auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities);
if (!ret.isOk()) {
ALOGE("%s: Unable to invoke callback", __func__);
}
diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h
index f02ab0a..72f7797 100644
--- a/gnss/2.0/default/Gnss.h
+++ b/gnss/2.0/default/Gnss.h
@@ -83,6 +83,7 @@
// Methods from V2_0::IGnss follow.
Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+ Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
@@ -91,6 +92,7 @@
getExtensionMeasurementCorrections() override;
Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
override;
+ Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
Return<bool> injectBestLocation_2_0(const V2_0::GnssLocation& location) override;
private:
diff --git a/gnss/2.0/default/GnssBatching.cpp b/gnss/2.0/default/GnssBatching.cpp
new file mode 100644
index 0000000..d56cdfb
--- /dev/null
+++ b/gnss/2.0/default/GnssBatching.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 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 "GnssBatching"
+
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+sp<V2_0::IGnssBatchingCallback> GnssBatching::sCallback = nullptr;
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<V1_0::IGnssBatchingCallback>&) {
+ // TODO implement
+ return bool{};
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ // TODO implement
+ return uint16_t{};
+}
+
+Return<bool> GnssBatching::start(const V1_0::IGnssBatching::Options&) {
+ // TODO implement
+ return bool{};
+}
+
+Return<void> GnssBatching::flush() {
+ // TODO implement
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ // TODO implement
+ return bool{};
+}
+
+Return<void> GnssBatching::cleanup() {
+ // TODO implement
+ return Void();
+}
+
+// Methods from V2_0::IGnssBatching follow.
+Return<bool> GnssBatching::init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) {
+ sCallback = callback;
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/2.0/default/GnssBatching.h b/gnss/2.0/default/GnssBatching.h
new file mode 100644
index 0000000..62ac580
--- /dev/null
+++ b/gnss/2.0/default/GnssBatching.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct GnssBatching : public IGnssBatching {
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<V1_0::IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const V1_0::IGnssBatching::Options& options) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ // Methods from V2_0::IGnssBatching follow.
+ Return<bool> init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) override;
+
+ private:
+ static sp<IGnssBatchingCallback> sCallback;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/2.0/default/GnssConfiguration.cpp b/gnss/2.0/default/GnssConfiguration.cpp
index 4389dd2..6bf1712 100644
--- a/gnss/2.0/default/GnssConfiguration.cpp
+++ b/gnss/2.0/default/GnssConfiguration.cpp
@@ -33,13 +33,11 @@
}
Return<bool> GnssConfiguration::setSuplVersion(uint32_t) {
- // TODO implement
- return bool{};
+ return true;
}
Return<bool> GnssConfiguration::setSuplMode(hidl_bitfield<SuplMode>) {
- // TODO implement
- return bool{};
+ return true;
}
Return<bool> GnssConfiguration::setGpsLock(hidl_bitfield<GpsLock> gpsLock) {
@@ -49,18 +47,15 @@
}
Return<bool> GnssConfiguration::setLppProfile(hidl_bitfield<LppProfile>) {
- // TODO implement
- return bool{};
+ return true;
}
Return<bool> GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol>) {
- // TODO implement
- return bool{};
+ return true;
}
Return<bool> GnssConfiguration::setEmergencySuplPdn(bool) {
- // TODO implement
- return bool{};
+ return true;
}
// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp
index 702c9e2..93de89c 100644
--- a/gnss/2.0/default/GnssMeasurement.cpp
+++ b/gnss/2.0/default/GnssMeasurement.cpp
@@ -26,7 +26,7 @@
namespace V2_0 {
namespace implementation {
-using GnssConstellationType = V1_0::GnssConstellationType;
+using GnssConstellationType = V2_0::GnssConstellationType;
using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
using GnssMeasurementState = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
@@ -46,6 +46,7 @@
}
Return<void> GnssMeasurement::close() {
+ ALOGD("close");
std::unique_lock<std::mutex> lock(mMutex);
stop();
sCallback = nullptr;
@@ -62,6 +63,7 @@
// Methods from V2_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
const sp<V2_0::IGnssMeasurementCallback>& callback, bool) {
+ ALOGD("setCallback_2_0");
std::unique_lock<std::mutex> lock(mMutex);
sCallback = callback;
@@ -75,6 +77,7 @@
}
void GnssMeasurement::start() {
+ ALOGD("start");
mIsActive = true;
mThread = std::thread([this]() {
while (mIsActive == true) {
@@ -87,6 +90,7 @@
}
void GnssMeasurement::stop() {
+ ALOGD("stop");
mIsActive = false;
if (mThread.joinable()) {
mThread.join();
@@ -95,27 +99,27 @@
GnssData GnssMeasurement::getMockMeasurement() {
V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = {
- .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY,
- .svid = (int16_t)6,
- .constellation = GnssConstellationType::GLONASS,
- .timeOffsetNs = 0.0,
- .receivedSvTimeInNs = 8195997131077,
- .receivedSvTimeUncertaintyInNs = 15,
- .cN0DbHz = 30.0,
- .pseudorangeRateMps = -484.13739013671875,
- .pseudorangeRateUncertaintyMps = 1.0379999876022339,
- .accumulatedDeltaRangeState = (uint32_t)
- V1_0::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN,
- .accumulatedDeltaRangeM = 0.0,
- .accumulatedDeltaRangeUncertaintyM = 0.0,
- .carrierFrequencyHz = 1.59975e+09,
- .multipathIndicator =
- V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN};
+ .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY,
+ .svid = (int16_t)6,
+ .constellation = V1_0::GnssConstellationType::UNKNOWN,
+ .timeOffsetNs = 0.0,
+ .receivedSvTimeInNs = 8195997131077,
+ .receivedSvTimeUncertaintyInNs = 15,
+ .cN0DbHz = 30.0,
+ .pseudorangeRateMps = -484.13739013671875,
+ .pseudorangeRateUncertaintyMps = 1.0379999876022339,
+ .accumulatedDeltaRangeState = (uint32_t)V1_0::IGnssMeasurementCallback::
+ GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN,
+ .accumulatedDeltaRangeM = 0.0,
+ .accumulatedDeltaRangeUncertaintyM = 0.0,
+ .carrierFrequencyHz = 1.59975e+09,
+ .multipathIndicator =
+ V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN};
V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0};
V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = {
.v1_1 = measurement_1_1,
- .codeType = IGnssMeasurementCallback::GnssMeasurementCodeType::C,
- .otherCodeTypeName = "",
+ .codeType = "C",
+ .constellation = GnssConstellationType::GLONASS,
.state = GnssMeasurementState::STATE_CODE_LOCK | GnssMeasurementState::STATE_BIT_SYNC |
GnssMeasurementState::STATE_SUBFRAME_SYNC |
GnssMeasurementState::STATE_TOW_DECODED |
diff --git a/gnss/2.0/default/GnssMeasurementCorrections.cpp b/gnss/2.0/default/GnssMeasurementCorrections.cpp
index cbf34ba..2bf5601 100644
--- a/gnss/2.0/default/GnssMeasurementCorrections.cpp
+++ b/gnss/2.0/default/GnssMeasurementCorrections.cpp
@@ -54,6 +54,19 @@
return true;
}
+Return<bool> GnssMeasurementCorrections::setCallback(
+ const sp<V1_0::IMeasurementCorrectionsCallback>& callback) {
+ using Capabilities = V1_0::IMeasurementCorrectionsCallback::Capabilities;
+ auto ret =
+ callback->setCapabilitiesCb(Capabilities::LOS_SATS | Capabilities::EXCESS_PATH_LENGTH |
+ Capabilities::REFLECTING_PLANE);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ return false;
+ }
+ return true;
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace measurement_corrections
diff --git a/gnss/2.0/default/GnssMeasurementCorrections.h b/gnss/2.0/default/GnssMeasurementCorrections.h
index f758bc8..4339bed 100644
--- a/gnss/2.0/default/GnssMeasurementCorrections.h
+++ b/gnss/2.0/default/GnssMeasurementCorrections.h
@@ -38,6 +38,7 @@
struct GnssMeasurementCorrections : public IMeasurementCorrections {
// Methods from V1_0::IMeasurementCorrections follow.
Return<bool> setCorrections(const MeasurementCorrections& corrections) override;
+ Return<bool> setCallback(const sp<V1_0::IMeasurementCorrectionsCallback>& callback) override;
};
} // namespace implementation
diff --git a/gnss/2.0/types.hal b/gnss/2.0/types.hal
index 4abb604..3865727 100644
--- a/gnss/2.0/types.hal
+++ b/gnss/2.0/types.hal
@@ -69,7 +69,31 @@
*
* This clock information can be obtained from SystemClock.elapsedRealtimeNanos(), when the GNSS
* is attached straight to the AP/SOC. When it is attached to a separate module the timestamp
- * needs to be estimatedd by syncing the notion of time via PTP or some other mechanism.
+ * needs to be estimated by syncing the notion of time via PTP or some other mechanism.
*/
ElapsedRealtime elapsedRealtime;
-};
\ No newline at end of file
+};
+
+/**
+ * GNSS constellation type
+ *
+ * This is to specify the navigation satellite system, for example, as listed in Section 3.5 in
+ * RINEX Version 3.04.
+ */
+enum GnssConstellationType : uint8_t {
+ UNKNOWN = 0,
+ /** Global Positioning System. */
+ GPS = 1,
+ /** Satellite-Based Augmentation System. */
+ SBAS = 2,
+ /** Global Navigation Satellite System. */
+ GLONASS = 3,
+ /** Quasi-Zenith Satellite System. */
+ QZSS = 4,
+ /** BeiDou Navigation Satellite System. */
+ BEIDOU = 5,
+ /** Galileo Navigation Satellite System. */
+ GALILEO = 6,
+ /** Indian Regional Navigation Satellite System. */
+ IRNSS = 7,
+};
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index c564f41..da6092b 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -26,6 +26,7 @@
GnssHalTest::GnssHalTest()
: info_called_count_(0),
capabilities_called_count_(0),
+ measurement_corrections_capabilities_called_count_(0),
location_called_count_(0),
name_called_count_(0),
notify_count_(0) {}
@@ -33,7 +34,7 @@
void GnssHalTest::SetUp() {
gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>(
GnssHidlEnvironment::Instance()->getServiceName<IGnss>());
- list_gnss_sv_status_.clear();
+ list_vec_gnss_sv_info_.clear();
ASSERT_NE(gnss_hal_, nullptr);
SetUpGnssCallback();
@@ -43,6 +44,7 @@
// Reset counters
info_called_count_ = 0;
capabilities_called_count_ = 0;
+ measurement_corrections_capabilities_called_count_ = 0;
location_called_count_ = 0;
name_called_count_ = 0;
measurement_called_count_ = 0;
@@ -59,7 +61,7 @@
gnss_cb_ = new GnssCallback(*this);
ASSERT_NE(gnss_cb_, nullptr);
- auto result = gnss_hal_->setCallback_1_1(gnss_cb_);
+ auto result = gnss_hal_->setCallback_2_0(gnss_cb_);
if (!result.isOk()) {
ALOGE("result of failed setCallback %s", result.description().c_str());
}
@@ -176,8 +178,19 @@
return status;
}
+std::cv_status GnssHalTest::waitForMeasurementCorrectionsCapabilities(int timeout_seconds) {
+ std::unique_lock<std::mutex> lock(mtx_);
+ auto status = std::cv_status::no_timeout;
+ while (measurement_corrections_capabilities_called_count_ == 0) {
+ status = cv_.wait_for(lock, std::chrono::seconds(timeout_seconds));
+ if (status == std::cv_status::timeout) return status;
+ }
+ notify_count_--;
+ return status;
+}
+
Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
- const IGnssCallback::GnssSystemInfo& info) {
+ const IGnssCallback_1_0::GnssSystemInfo& info) {
ALOGI("Info received, year %d", info.yearOfHw);
parent_.info_called_count_++;
parent_.last_info_ = info;
@@ -228,10 +241,9 @@
return Void();
}
-Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb(
- const IGnssCallback::GnssSvStatus& svStatus) {
- ALOGI("GnssSvStatus received");
- parent_.list_gnss_sv_status_.emplace_back(svStatus);
+Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) {
+ ALOGI("gnssSvStatusCb");
+
return Void();
}
@@ -243,3 +255,20 @@
parent_.notify();
return Void();
}
+
+Return<void> GnssHalTest::GnssMeasurementCorrectionsCallback::setCapabilitiesCb(
+ uint32_t capabilities) {
+ ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities);
+ parent_.measurement_corrections_capabilities_called_count_++;
+ parent_.last_measurement_corrections_capabilities_ = capabilities;
+ parent_.notify();
+ return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb_2_0(
+ const hidl_vec<IGnssCallback_2_0::GnssSvInfo>& svInfoList) {
+ ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size());
+ parent_.list_vec_gnss_sv_info_.emplace_back(svInfoList);
+ parent_.notify();
+ return Void();
+}
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index 31750a6..737815f 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -25,16 +25,20 @@
#include <list>
#include <mutex>
+using android::hardware::hidl_vec;
using android::hardware::Return;
using android::hardware::Void;
+using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
using android::hardware::gnss::V1_0::GnssLocationFlags;
using android::hardware::gnss::V2_0::IGnss;
-using android::hardware::gnss::V2_0::IGnssCallback;
using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
+using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback;
+using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback;
+
using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
@@ -73,9 +77,11 @@
/* Test code calls this function to wait for a callback */
std::cv_status wait(int timeout_seconds);
+ std::cv_status waitForMeasurementCorrectionsCapabilities(int timeout_seconds);
+
/* Callback class for data & Event. */
- class GnssCallback : public IGnssCallback {
- public:
+ class GnssCallback : public IGnssCallback_2_0 {
+ public:
GnssHalTest& parent_;
GnssCallback(GnssHalTest& parent) : parent_(parent){};
@@ -83,7 +89,7 @@
virtual ~GnssCallback() = default;
// Dummy callback handlers
- Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue /* status */) override {
+ Return<void> gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override {
return Void();
}
Return<void> gnssNmeaCb(int64_t /* timestamp */,
@@ -100,8 +106,8 @@
Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
Return<void> gnssLocationCb(const GnssLocation_1_0& location) override;
Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
- Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
- Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
+ Return<void> gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override;
+ Return<void> gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override;
// New in v2.0
Return<void> gnssLocationCb_2_0(const GnssLocation_2_0& location) override;
@@ -110,6 +116,8 @@
return Void();
}
Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
+ Return<void> gnssSvStatusCb_2_0(
+ const hidl_vec<IGnssCallback_2_0::GnssSvInfo>& svInfoList) override;
private:
Return<void> gnssLocationCbImpl(const GnssLocation_2_0& location);
@@ -136,6 +144,17 @@
Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override;
};
+ /* Callback class for GnssMeasurementCorrections. */
+ class GnssMeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback {
+ public:
+ GnssHalTest& parent_;
+ GnssMeasurementCorrectionsCallback(GnssHalTest& parent) : parent_(parent){};
+ virtual ~GnssMeasurementCorrectionsCallback() = default;
+
+ // Methods from V1_0::IMeasurementCorrectionsCallback follow.
+ Return<void> setCapabilitiesCb(uint32_t capabilities) override;
+ };
+
/*
* SetUpGnssCallback:
* Set GnssCallback and verify the result.
@@ -184,7 +203,7 @@
void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
sp<IGnss> gnss_hal_; // GNSS HAL to call into
- sp<IGnssCallback> gnss_cb_; // Primary callback interface
+ sp<IGnssCallback_2_0> gnss_cb_; // Primary callback interface
// TODO: make these variables thread-safe.
/* Count of calls to set the following items, and the latest item (used by
@@ -192,19 +211,21 @@
*/
int info_called_count_;
int capabilities_called_count_;
+ int measurement_corrections_capabilities_called_count_;
int location_called_count_;
int measurement_called_count_;
int name_called_count_;
- IGnssCallback::GnssSystemInfo last_info_;
+ IGnssCallback_1_0::GnssSystemInfo last_info_;
uint32_t last_capabilities_;
+ uint32_t last_measurement_corrections_capabilities_;
GnssLocation_2_0 last_location_;
IGnssMeasurementCallback_2_0::GnssData last_measurement_;
android::hardware::hidl_string last_name_;
- list<IGnssCallback::GnssSvStatus> list_gnss_sv_status_;
+ list<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> list_vec_gnss_sv_info_;
- private:
+ private:
std::mutex mtx_;
std::condition_variable cv_;
int notify_count_;
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 3703eba..0682f84 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -32,12 +32,16 @@
using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss;
using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss;
using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
+using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching;
+using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching;
using android::hardware::gnss::common::Utils;
using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
using android::hardware::gnss::V1_0::IGnssNi;
using android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
+using android::hardware::gnss::V2_0::GnssConstellationType;
+using android::hardware::gnss::V2_0::IGnssCallback;
using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
/*
@@ -50,23 +54,21 @@
/*
* TestGnssMeasurementCallback:
- * Gets the GnssMeasurementExtension and verify that it returns an actual extension.
+ * Gets the GnssMeasurementExtension and verifies that it returns an actual extension.
*/
TEST_F(GnssHalTest, TestGnssMeasurementCallback) {
auto gnssMeasurement_2_0 = gnss_hal_->getExtensionGnssMeasurement_2_0();
auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1();
auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
- ASSERT_TRUE(gnssMeasurement_2_0.isOk() || gnssMeasurement_1_1.isOk() ||
+ ASSERT_TRUE(gnssMeasurement_2_0.isOk() && gnssMeasurement_1_1.isOk() &&
gnssMeasurement_1_0.isOk());
- if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) {
- sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
- sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
- sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
- // At least one interface is non-null.
- int numNonNull = (int)(iGnssMeas_2_0 != nullptr) + (int)(iGnssMeas_1_1 != nullptr) +
- (int)(iGnssMeas_1_0 != nullptr);
- ASSERT_TRUE(numNonNull >= 1);
- }
+ sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
+ sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
+ sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
+ // At least one interface is non-null.
+ int numNonNull = (int)(iGnssMeas_2_0 != nullptr) + (int)(iGnssMeas_1_1 != nullptr) +
+ (int)(iGnssMeas_1_0 != nullptr);
+ ASSERT_TRUE(numNonNull >= 1);
}
/*
@@ -164,10 +166,13 @@
}
/*
- * TestGnssMeasurementCodeType:
- * Sets a GnssMeasurementCallback, waits for a measurement, and verifies the codeType is valid.
+ * TestGnssMeasurementFields:
+ * Sets a GnssMeasurementCallback, waits for a measurement, and verifies
+ * 1. codeType is valid,
+ * 2. constellation is valid.
+ * 3. state is valid.
*/
-TEST_F(GnssHalTest, TestGnssMeasurementCodeType) {
+TEST_F(GnssHalTest, TestGnssMeasurementFields) {
const int kFirstGnssMeasurementTimeoutSeconds = 10;
auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_0();
@@ -190,17 +195,23 @@
EXPECT_EQ(measurement_called_count_, 1);
ASSERT_TRUE(last_measurement_.measurements.size() > 0);
for (auto measurement : last_measurement_.measurements) {
+ // Verify CodeType is valid.
+ ASSERT_NE(measurement.codeType, "");
+
+ // Verify ConstellationType is valid.
+ ASSERT_TRUE(static_cast<uint8_t>(measurement.constellation) >=
+ static_cast<uint8_t>(GnssConstellationType::UNKNOWN) &&
+ static_cast<uint8_t>(measurement.constellation) <=
+ static_cast<uint8_t>(GnssConstellationType::IRNSS));
+
+ // Verify State is valid.
ASSERT_TRUE(
- ((int)measurement.codeType >=
- (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::A &&
- (int)measurement.codeType <=
- (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::N) ||
- (int)measurement.codeType ==
- (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::OTHER);
- if ((int)measurement.codeType ==
- (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::OTHER) {
- ASSERT_NE(measurement.otherCodeTypeName, "");
- }
+ static_cast<uint32_t>(measurement.state) >=
+ static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
+ STATE_UNKNOWN) &&
+ static_cast<uint32_t>(measurement.state) <=
+ static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
+ STATE_2ND_CODE_LOCK));
}
iGnssMeasurement->close();
@@ -277,8 +288,35 @@
}
/*
+ * TestGnssMeasurementCorrectionsCapabilities:
+ * If the GnssMeasurementCorrectionsExtension is not null, verifies that the measurement corrections
+ * capabilities are reported and the mandatory LOS_SATS or the EXCESS_PATH_LENGTH
+ * capability flag is set.
+ */
+TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) {
+ // Setup measurement corrections callback.
+ auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections();
+ ASSERT_TRUE(measurementCorrections.isOk());
+ sp<IMeasurementCorrections> iMeasurementCorrections = measurementCorrections;
+ if (iMeasurementCorrections == nullptr) {
+ return;
+ }
+
+ sp<IMeasurementCorrectionsCallback> iMeasurementCorrectionsCallback =
+ new GnssMeasurementCorrectionsCallback(*this);
+ iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback);
+
+ const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5;
+ waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds);
+ ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0);
+ using Capabilities = IMeasurementCorrectionsCallback::Capabilities;
+ ASSERT_TRUE((last_measurement_corrections_capabilities_ &
+ (Capabilities::LOS_SATS | Capabilities::EXCESS_PATH_LENGTH)) != 0);
+}
+
+/*
* TestGnssMeasurementCorrections:
- * Gets the GnssMeasurementCorrectionsExtension and verifies that it supports the
+ * If the GnssMeasurementCorrectionsExtension is not null, verifies that it supports the
* gnss.measurement_corrections@1.0::IMeasurementCorrections interface by invoking a method.
*/
TEST_F(GnssHalTest, TestGnssMeasurementCorrections) {
@@ -286,8 +324,17 @@
auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections();
ASSERT_TRUE(measurementCorrections.isOk());
sp<IMeasurementCorrections> iMeasurementCorrections = measurementCorrections;
- ASSERT_NE(iMeasurementCorrections, nullptr);
+ if (iMeasurementCorrections == nullptr) {
+ return;
+ }
+ sp<IMeasurementCorrectionsCallback> iMeasurementCorrectionsCallback =
+ new GnssMeasurementCorrectionsCallback(*this);
+ iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback);
+
+ const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5;
+ waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds);
+ ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0);
// Set a mock MeasurementCorrections.
auto result = iMeasurementCorrections->setCorrections(Utils::getMockMeasurementCorrections());
ASSERT_TRUE(result.isOk());
@@ -321,9 +368,9 @@
wait(kFirstGnssMeasurementTimeoutSeconds);
EXPECT_EQ(measurement_called_count_, 1);
- ASSERT_TRUE((int)last_measurement_.elapsedRealtime.flags >= 0 &&
- (int)last_measurement_.elapsedRealtime.flags <=
- (int)ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS);
+ ASSERT_TRUE((int)last_measurement_.elapsedRealtime.flags <=
+ (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS));
// We expect a non-zero timestamp when set.
if (last_measurement_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
@@ -336,9 +383,9 @@
TEST_F(GnssHalTest, TestGnssLocationElapsedRealtime) {
StartAndCheckFirstLocation();
- ASSERT_TRUE((int)last_location_.elapsedRealtime.flags >= 0 &&
- (int)last_location_.elapsedRealtime.flags <=
- (int)ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS);
+ ASSERT_TRUE((int)last_location_.elapsedRealtime.flags <=
+ (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS));
// We expect a non-zero timestamp when set.
if (last_location_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
@@ -354,3 +401,20 @@
gnss_hal_->injectBestLocation_2_0(last_location_);
StopAndClearLocations();
}
+
+/*
+ * TestGnssBatchingExtension:
+ * Gets the GnssBatchingExtension and verifies that it supports either the @1.0::IGnssBatching
+ * or @2.0::IGnssBatching extension.
+ */
+TEST_F(GnssHalTest, TestGnssBatchingExtension) {
+ auto gnssBatching_V2_0 = gnss_hal_->getExtensionGnssBatching_2_0();
+ ASSERT_TRUE(gnssBatching_V2_0.isOk());
+
+ auto gnssBatching_V1_0 = gnss_hal_->getExtensionGnssBatching();
+ ASSERT_TRUE(gnssBatching_V1_0.isOk());
+
+ sp<IGnssBatching_V1_0> iGnssBatching_V1_0 = gnssBatching_V1_0;
+ sp<IGnssBatching_V2_0> iGnssBatching_V2_0 = gnssBatching_V2_0;
+ ASSERT_TRUE(iGnssBatching_V1_0 != nullptr || iGnssBatching_V2_0 != nullptr);
+}
diff --git a/gnss/measurement_corrections/1.0/Android.bp b/gnss/measurement_corrections/1.0/Android.bp
index 4aac7e0..456b55c 100644
--- a/gnss/measurement_corrections/1.0/Android.bp
+++ b/gnss/measurement_corrections/1.0/Android.bp
@@ -9,6 +9,7 @@
srcs: [
"types.hal",
"IMeasurementCorrections.hal",
+ "IMeasurementCorrectionsCallback.hal",
],
interfaces: [
"android.hardware.gnss@1.0",
diff --git a/gnss/measurement_corrections/1.0/IMeasurementCorrections.hal b/gnss/measurement_corrections/1.0/IMeasurementCorrections.hal
index 934d10f..1fa32f4 100644
--- a/gnss/measurement_corrections/1.0/IMeasurementCorrections.hal
+++ b/gnss/measurement_corrections/1.0/IMeasurementCorrections.hal
@@ -16,11 +16,12 @@
package android.hardware.gnss.measurement_corrections@1.0;
+import IMeasurementCorrectionsCallback;
+
/**
* Interface for measurement corrections support.
*/
interface IMeasurementCorrections {
-
/**
* Injects measurement corrections to be used by the HAL to improve the GNSS location output.
*
@@ -35,5 +36,15 @@
*
* @return success Whether the HAL can accept & use these corrections.
*/
- setCorrections(MeasurementCorrections corrections) generates (bool success);
-};
+ setCorrections(MeasurementCorrections corrections) generates (bool success);
+
+ /**
+ * Opens the interface and provides the callback routines to the implementation of this
+ * interface.
+ *
+ * @param callback Callback interface for IMeasurementCorrections.
+ *
+ * @return success Returns true on success.
+ */
+ setCallback(IMeasurementCorrectionsCallback callback) generates (bool success);
+};
\ No newline at end of file
diff --git a/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.hal b/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.hal
new file mode 100644
index 0000000..91d1311
--- /dev/null
+++ b/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.hal
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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.gnss.measurement_corrections@1.0;
+
+/**
+ * GNSS measurement corrections callback interface.
+ */
+interface IMeasurementCorrectionsCallback {
+
+ /**
+ * Flags to indicate supported measurement corrections capabilities
+ *
+ * Either the LOS_SATS or the EXCESS_PATH_LENGTH capability must be supported.
+ */
+ enum Capabilities : uint32_t {
+ /** GNSS supports line-of-sight satellite identification measurement corrections */
+ LOS_SATS = 1 << 0,
+ /** GNSS supports per satellite excess-path-length measurement corrections */
+ EXCESS_PATH_LENGTH = 1 << 1,
+ /** GNSS supports reflecting planes measurement corrections */
+ REFLECTING_PLANE = 1 << 2
+ };
+
+ /**
+ * Callback to inform framework the measurement correction specific capabilities of the GNSS
+ * HAL implementation.
+ *
+ * The GNSS HAL must call this method immediately after the framework opens the measurement
+ * corrections interface.
+ *
+ * @param capabilities Supported measurement corrections capabilities. It is mandatory to
+ * support either LOS_STATS or EXCESS_PATH_LENGTH capability.
+ *
+ */
+ setCapabilitiesCb(bitfield<Capabilities> capabilities);
+};
\ No newline at end of file
diff --git a/graphics/bufferqueue/1.0/IGraphicBufferProducer.hal b/graphics/bufferqueue/1.0/IGraphicBufferProducer.hal
index c59a16c..21cbc2e 100644
--- a/graphics/bufferqueue/1.0/IGraphicBufferProducer.hal
+++ b/graphics/bufferqueue/1.0/IGraphicBufferProducer.hal
@@ -546,7 +546,7 @@
*/
disconnect(
int32_t api,
- DisconnectMode mode /* = DisconnectMode::API */
+ DisconnectMode mode
) generates (
Status status
);
diff --git a/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal b/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal
index 734c0b4..23b360a 100644
--- a/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal
+++ b/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal
@@ -75,12 +75,19 @@
* @param slot Slot index.
* @return status Status of the call.
* @return buffer New buffer associated to the given slot index.
+ * @return generationNumber Generation number of the buffer. If
+ * requestBuffer() is called immediately after dequeueBuffer() returns
+ * with `bufferNeedsReallocation` set to `true`, @p generationNumber must
+ * match the current generation number of the buffer queue previously
+ * set by setGenerationNumber(). Otherwise, @p generationNumber may not
+ * match the current generation number of the buffer queue.
*/
requestBuffer(
int32_t slot
) generates (
Status status,
- HardwareBuffer buffer
+ HardwareBuffer buffer,
+ uint32_t generationNumber
);
/**
@@ -212,9 +219,9 @@
* parameter.
*
* @param input See #DequeueBufferInput for more information.
- * @param status Status of the call.
- * @param slot Slot index.
- * @param output See #DequeueBufferOutput for more information.
+ * @return status Status of the call.
+ * @return slot Slot index.
+ * @return output See #DequeueBufferOutput for more information.
*
* @sa queueBuffer(), requestBuffer().
*/
@@ -286,6 +293,9 @@
* See dequeueBuffer() for conditions that may cause the call to fail.
*
* @param buffer Buffer to attach to the buffer queue.
+ * @param generationNumber Generation number of the buffer. If this does not
+ * match the current generation number of the buffer queue, the call
+ * must fail with @p status set to `BAD_VALUE`.
* @return status Status of the call.
* @return slot Slot index assigned to @p buffer.
* @return releaseAllBuffers Whether the caller is expected to release all
@@ -294,7 +304,8 @@
* @sa dequeueBuffer().
*/
attachBuffer(
- HardwareBuffer buffer
+ HardwareBuffer buffer,
+ uint32_t generationNumber
) generates (
Status status,
int32_t slot,
diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal
index 5fcc0e6..1eea306 100644
--- a/graphics/composer/2.3/IComposerClient.hal
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -61,6 +61,11 @@
* PowerMode::DOZE_SUSPEND.
*/
DOZE = 2,
+
+ /**
+ * Indicates that the display supports brightness operations.
+ */
+ BRIGHTNESS = 3,
};
/**
@@ -495,4 +500,38 @@
float maxLuminance,
float maxAverageLuminance,
float minLuminance);
+
+ /**
+ * Gets whether brightness operations are supported on a display.
+ *
+ * @param display
+ * The display.
+ *
+ * @return error is NONE upon success. Otherwise,
+ * BAD_DISPLAY when the display is invalid, or
+ * BAD_PARAMETER when the output parameter is invalid.
+ * @return support
+ * Whether brightness operations are supported on the display.
+ */
+ getDisplayBrightnessSupport(Display display) generates (Error error, bool support);
+
+ /**
+ * Sets the brightness of a display.
+ *
+ * Ideally, the brightness change should take effect in the next frame post (so that it can be
+ * aligned with color transforms).
+ *
+ * @param display
+ * The display whose brightness is set.
+ * @param brightness
+ * A number between 0.0f (minimum brightness) and 1.0f (maximum brightness), or -1.0 to
+ * turn the backlight off.
+ *
+ * @return error is NONE upon success. Otherwise,
+ * BAD_DISPLAY when the display is invalid, or
+ * UNSUPPORTED when brightness operations are not supported, or
+ * BAD_PARAMETER when the brightness is invalid, or
+ * NO_RESOURCES when the brightness cannot be applied.
+ */
+ setDisplayBrightness(Display display, float brightness) generates (Error error);
};
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
index a272e72..1b40795 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
@@ -172,7 +172,19 @@
return Void();
}
- protected:
+ Return<void> getDisplayBrightnessSupport(
+ Display display, IComposerClient::getDisplayBrightnessSupport_cb hidl_cb) override {
+ bool support = false;
+ Error error = mHal->getDisplayBrightnessSupport(display, &support);
+ hidl_cb(error, support);
+ return Void();
+ }
+
+ Return<Error> setDisplayBrightness(Display display, float brightness) override {
+ return mHal->setDisplayBrightness(display, brightness);
+ }
+
+ protected:
std::unique_ptr<V2_1::hal::ComposerCommandEngine> createCommandEngine() override {
return std::make_unique<ComposerCommandEngine>(
mHal, static_cast<V2_2::hal::ComposerResources*>(mResources.get()));
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
index a0812ad..186b004 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
@@ -119,6 +119,8 @@
virtual Error setLayerPerFrameMetadataBlobs(
Display display, Layer layer,
std::vector<IComposerClient::PerFrameMetadataBlob>& blobs) = 0;
+ virtual Error getDisplayBrightnessSupport(Display display, bool* outSupport) = 0;
+ virtual Error setDisplayBrightness(Display display, float brightness) = 0;
};
} // namespace hal
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
index 41e333a..070cf80 100644
--- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -245,7 +245,29 @@
return static_cast<Error>(err);
}
- protected:
+ Error getDisplayBrightnessSupport(Display display, bool* outSupport) {
+ if (!mDispatch.getDisplayBrightnessSupport) {
+ return Error::UNSUPPORTED;
+ }
+ bool support = false;
+ int32_t error = mDispatch.getDisplayBrightnessSupport(mDevice, display, &support);
+ *outSupport = support;
+ return static_cast<Error>(error);
+ }
+
+ Error setDisplayBrightness(Display display, float brightness) {
+ if (std::isnan(brightness) || brightness > 1.0f ||
+ (brightness < 0.0f && brightness != -1.0f)) {
+ return Error::BAD_PARAMETER;
+ }
+ if (!mDispatch.setDisplayBrightness) {
+ return Error::UNSUPPORTED;
+ }
+ int32_t error = mDispatch.setDisplayBrightness(mDevice, display, brightness);
+ return static_cast<Error>(error);
+ }
+
+ protected:
bool initDispatch() override {
if (!BaseType2_2::initDispatch()) {
return false;
@@ -265,6 +287,10 @@
&mDispatch.getDisplayCapabilities);
this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS,
&mDispatch.setLayerPerFrameMetadataBlobs);
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT,
+ &mDispatch.getDisplayBrightnessSupport);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS,
+ &mDispatch.setDisplayBrightness);
return true;
}
@@ -277,6 +303,8 @@
HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLE getDisplayedContentSample;
HWC2_PFN_GET_DISPLAY_CAPABILITIES getDisplayCapabilities;
HWC2_PFN_SET_LAYER_PER_FRAME_METADATA_BLOBS setLayerPerFrameMetadataBlobs;
+ HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT getDisplayBrightnessSupport;
+ HWC2_PFN_SET_DISPLAY_BRIGHTNESS setDisplayBrightness;
} mDispatch = {};
using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>;
diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
index 0e541ed..4de85d6 100644
--- a/graphics/composer/2.3/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
@@ -186,6 +186,19 @@
return capabilities;
}
+bool ComposerClient::getDisplayBrightnessSupport(Display display) {
+ bool support = false;
+ mClient->getDisplayBrightnessSupport(display, [&](const auto& error, const auto& tmpSupport) {
+ ASSERT_EQ(Error::NONE, error) << "failed to get brightness support";
+ support = tmpSupport;
+ });
+ return support;
+}
+
+Error ComposerClient::setDisplayBrightness(Display display, float brightness) {
+ return mClient->setDisplayBrightness(display, brightness);
+}
+
} // namespace vts
} // namespace V2_3
} // namespace composer
diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
index ad4ef0b..a0e764d 100644
--- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
+++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
@@ -52,7 +52,7 @@
std::unique_ptr<ComposerClient> createClient();
- protected:
+ protected:
explicit Composer(const sp<IComposer>& composer);
private:
@@ -99,7 +99,11 @@
std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys_2_3(Display display);
- private:
+ bool getDisplayBrightnessSupport(Display display);
+
+ Error setDisplayBrightness(Display display, float brightness);
+
+ private:
const sp<IComposerClient> mClient;
};
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index de74e28..b983e42 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -600,6 +600,36 @@
}
}
+/*
+ * Test that getDisplayBrightnessSupport works as expected.
+ */
+TEST_F(GraphicsComposerHidlTest, getDisplayBrightnessSupport) {
+ auto capabilities = mComposerClient->getDisplayCapabilities(mPrimaryDisplay);
+ bool brightnessSupport =
+ std::find(capabilities.begin(), capabilities.end(),
+ IComposerClient::DisplayCapability::BRIGHTNESS) != capabilities.end();
+ EXPECT_EQ(mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay), brightnessSupport);
+}
+
+/*
+ * Test that if brightness operations are supported, setDisplayBrightness works as expected.
+ */
+TEST_F(GraphicsComposerHidlTest, setDisplayBrightness) {
+ if (!mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay)) {
+ EXPECT_EQ(mComposerClient->getRaw()->setDisplayBrightness(mPrimaryDisplay, 0.5f),
+ Error::UNSUPPORTED);
+ GTEST_SUCCEED() << "Brightness operations are not supported";
+ }
+
+ EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.0f), Error::NONE);
+ EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.5f), Error::NONE);
+ EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 1.0f), Error::NONE);
+ EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, -1.0f), Error::NONE);
+
+ EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, +2.0f), Error::BAD_PARAMETER);
+ EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, -2.0f), Error::BAD_PARAMETER);
+}
+
} // namespace
} // namespace vts
} // namespace V2_3
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp
index 9325cc0..e8db074 100644
--- a/keymaster/4.0/support/Keymaster.cpp
+++ b/keymaster/4.0/support/Keymaster.cpp
@@ -106,6 +106,19 @@
return result;
}
+void Keymaster::logIfKeymasterVendorError(ErrorCode ec) const {
+ static constexpr int32_t k_keymaster_vendor_error_code_range_max = -10000;
+ if (static_cast<int32_t>(ec) <= k_keymaster_vendor_error_code_range_max) {
+ const auto& versionInfo = halVersion();
+ LOG(ERROR) << "Keymaster reported error: " << static_cast<int32_t>(ec) << "\n"
+ << "NOTE: This is an error in the vendor specific error range.\n"
+ << " Refer to the vendor of the implementation for details.\n"
+ << " Implementation name: " << versionInfo.keymasterName << "\n"
+ << " Vendor name: " << versionInfo.authorName << "\n"
+ << " MajorVersion: " << versionInfo.majorVersion;
+ }
+}
+
Keymaster::KeymasterSet Keymaster::enumerateAvailableDevices() {
auto serviceManager = IServiceManager::getService();
CHECK(serviceManager) << "Could not retrieve ServiceManager";
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
index 458053a..43a34b0 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
@@ -65,6 +65,12 @@
const hidl_string& instanceName() const { return instanceName_; }
/**
+ * If ec is in the vendor error code range (<-10000), logs the fact to logcat.
+ * There are no side effects otherwise.
+ */
+ void logIfKeymasterVendorError(ErrorCode ec) const;
+
+ /**
* Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least
* secure (as defined by VersionResult::operator<).
*/
diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
index 6c836af..7307a81 100644
--- a/media/c2/1.0/Android.bp
+++ b/media/c2/1.0/Android.bp
@@ -19,7 +19,10 @@
],
interfaces: [
"android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
"android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
"android.hardware.media.bufferpool@2.0",
"android.hardware.media.omx@1.0",
"android.hardware.media@1.0",
diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal
index abd1448..51ef4e1 100644
--- a/media/c2/1.0/IComponent.hal
+++ b/media/c2/1.0/IComponent.hal
@@ -17,6 +17,7 @@
package android.hardware.media.c2@1.0;
import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer;
import android.hardware.media.omx@1.0::IGraphicBufferSource;
import IConfigurable;
@@ -128,7 +129,7 @@
*/
setOutputSurface(
uint64_t blockPoolId,
- IGraphicBufferProducer surface
+ @2.0::IGraphicBufferProducer surface
) generates (
Status status
);
@@ -184,7 +185,7 @@
* null.
*/
connectToOmxInputSurface(
- IGraphicBufferProducer producer,
+ @1.0::IGraphicBufferProducer producer,
IGraphicBufferSource source
) generates (
Status status,
diff --git a/media/c2/1.0/IInputSink.hal b/media/c2/1.0/IInputSink.hal
index 809c27a..767eb73 100644
--- a/media/c2/1.0/IInputSink.hal
+++ b/media/c2/1.0/IInputSink.hal
@@ -16,8 +16,6 @@
package android.hardware.media.c2@1.0;
-import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
-
import IConfigurable;
/**
diff --git a/media/c2/1.0/IInputSurface.hal b/media/c2/1.0/IInputSurface.hal
index d11ce15..3eee7f1 100644
--- a/media/c2/1.0/IInputSurface.hal
+++ b/media/c2/1.0/IInputSurface.hal
@@ -16,7 +16,7 @@
package android.hardware.media.c2@1.0;
-import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer;
import IConfigurable;
import IInputSink;
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index 88a9e26..f299e36 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -387,17 +387,28 @@
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+ OMX_PARAM_PORTDEFINITIONTYPE portDefInput;
+ OMX_PARAM_PORTDEFINITIONTYPE portDefOutput;
+ status = getPortParam(omxNode, OMX_IndexParamPortDefinition, kPortIndexInput, &portDefInput);
+ EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+ status = getPortParam(omxNode, OMX_IndexParamPortDefinition, kPortIndexOutput, &portDefOutput);
+ EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
// Dont switch states until the ports are populated
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
- ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+ if (portDefInput.nBufferCountActual || portDefOutput.nBufferCountActual) {
+ status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+ ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+ }
// allocate buffers on input port
ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
omxNode, iBuffer, kPortIndexInput, pm[0], allocGrap));
// Dont switch states until the ports are populated
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
- ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+ if (portDefOutput.nBufferCountActual) {
+ status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+ ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+ }
// allocate buffers on output port
ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
@@ -430,9 +441,18 @@
OMX_StateLoaded);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+ OMX_PARAM_PORTDEFINITIONTYPE portDefInput;
+ OMX_PARAM_PORTDEFINITIONTYPE portDefOutput;
+ status = getPortParam(omxNode, OMX_IndexParamPortDefinition, kPortIndexInput, &portDefInput);
+ EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+ status = getPortParam(omxNode, OMX_IndexParamPortDefinition, kPortIndexOutput, &portDefOutput);
+ EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
// dont change state until all buffers are freed
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
- ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+ if (portDefInput.nBufferCountActual || portDefOutput.nBufferCountActual) {
+ status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+ ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+ }
for (size_t i = 0; i < iBuffer->size(); ++i) {
status = omxNode->freeBuffer(kPortIndexInput, (*iBuffer)[i].id);
@@ -440,8 +460,10 @@
}
// dont change state until all buffers are freed
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
- ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+ if (portDefOutput.nBufferCountActual) {
+ status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+ ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+ }
for (size_t i = 0; i < oBuffer->size(); ++i) {
status = omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 4ddc833..1c1d39b 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -115,6 +115,7 @@
}
if (compClass == unknown_class) disableTest = true;
isSecure = false;
+ mTunnel = false;
size_t suffixLen = strlen(".secure");
if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
isSecure =
@@ -122,6 +123,18 @@
strlen(gEnv->getComponent().c_str()) - suffixLen,
".secure");
}
+ if (compClass == video_decoder) {
+ omxNode->configureVideoTunnelMode(
+ 1, OMX_TRUE, 0,
+ [&](android::hardware::media::omx::V1_0::Status _s,
+ const ::android::hardware::hidl_handle& sidebandHandle) {
+ (void)sidebandHandle;
+ if (_s == android::hardware::media::omx::V1_0::Status::OK)
+ this->mTunnel = true;
+ });
+ }
+ // NOTES: secure components are not covered in these tests.
+ // we are disabling tests for them
if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
}
@@ -149,6 +162,7 @@
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
standardCompClass compClass;
+ bool mTunnel;
bool isSecure;
bool disableTest;
@@ -991,7 +1005,8 @@
ASSERT_NO_FATAL_FAILURE(
changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
kPortIndexInput, kPortIndexOutput, portMode));
- for (size_t i = portBase; i < portBase + 2; i++) {
+ int range = mTunnel ? 1 : 2;
+ for (size_t i = portBase; i < portBase + range; i++) {
status =
omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -1104,7 +1119,8 @@
dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1]));
}
- for (size_t i = portBase; i < portBase + 2; i++) {
+ int range = mTunnel ? 1 : 2;
+ for (size_t i = portBase; i < portBase + range; i++) {
status =
omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
index 1db9f75..df048c6 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
@@ -153,7 +153,17 @@
".secure");
}
if (isSecure) disableTest = true;
+ omxNode->configureVideoTunnelMode(
+ 1, OMX_TRUE, 0,
+ [&](android::hardware::media::omx::V1_0::Status _s,
+ const ::android::hardware::hidl_handle& sidebandHandle) {
+ (void)sidebandHandle;
+ if (_s == android::hardware::media::omx::V1_0::Status::OK)
+ this->disableTest = true;
+ });
if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
+ // NOTES: secure and tunneled components are not covered in these tests.
+ // we are disabling tests for them
}
virtual void TearDown() override {
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 7eea7fc..106f332 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -52,6 +52,7 @@
using ::test_helper::MixedTyped;
using ::test_helper::MixedTypedExample;
using ::test_helper::resize_accordingly;
+using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
template <typename T>
void copy_back_(std::map<int, std::vector<T>>* dst, const std::vector<RequestArgument>& ra,
@@ -77,6 +78,13 @@
"Number of types in MixedTyped changed, but copy_back function wasn't updated");
}
+static bool isZeroSized(const MixedTyped& example, uint32_t index) {
+ for (auto i : example.operandDimensions.at(index)) {
+ if (i == 0) return true;
+ }
+ return false;
+}
+
// Top level driver for models and examples generated by test_generator.py
// Test driver for those generated from ml/nn/runtime/test/spec
static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>& preparedModel,
@@ -178,17 +186,18 @@
// Go through all outputs, initialize RequestArgument descriptors
resize_accordingly(golden, test);
bool sizeLargerThanOne = true;
- for_all(golden, [&outputs_info, &outputSize, &outputType, &sizeLargerThanOne](
+ for_all(golden, [&golden, &outputs_info, &outputSize, &outputType, &sizeLargerThanOne](
int index, auto, auto s) {
if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
if (index == 0) {
// On OutputType::INSUFFICIENT, set the output operand with index 0 with
// buffer size one byte less than needed.
if (outputType == OutputType::INSUFFICIENT) {
- if (s > 1)
+ if (s > 1 && !isZeroSized(golden, index)) {
s -= 1;
- else
+ } else {
sizeLargerThanOne = false;
+ }
}
}
RequestArgument arg = {
@@ -532,7 +541,8 @@
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
- model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
+ model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec<hidl_handle>(),
+ hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index c9de76b..99f873a 100644
--- a/neuralnetworks/1.1/types.hal
+++ b/neuralnetworks/1.1/types.hal
@@ -186,7 +186,8 @@
* must be >= 1.
* * 2: A 2-D Tensor of {@link OperandType::TENSOR_INT32}, the paddings
* for each spatial dimension of the input tensor. All values must be
- * >= 0. The shape of the tensor must be {rank(input0), 2}.
+ * >= 0. The shape of the tensor must be {M, 2}, where M is the number
+ * of spatial dimensions.
* padding[i, 0] specifies the number of element to be padded in the
* front of dimension i.
* padding[i, 1] specifies the number of element to be padded after the
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index b9fa388..da9a966 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -113,44 +113,83 @@
generates (ErrorStatus status, vec<bool> supportedOperations);
/**
- * Gets whether the driver supports compilation caching.
+ * Gets the caching requirements of the driver implementation.
*
- * isCachingSupported indicates whether the driver supports compilation caching.
- * Even if so, the driver may still choose not to cache certain compiled models.
+ * There are two types of cache file descriptors provided to the driver: model cache
+ * and data cache.
*
- * If the device reports the caching is not supported, the user may avoid calling
- * IDevice::prepareModelFromCache and IPreparedModel::saveToCache.
+ * The data cache is for caching constant data, possibly including preprocessed
+ * and transformed tensor buffers. Any modification to the data cache should
+ * have no worse effect than generating bad output values at execution time.
+ *
+ * The model cache is for caching security-sensitive data such as compiled
+ * executable machine code in the device's native binary format. A modification
+ * to the model cache may affect the driver's execution behavior, and a malicious
+ * client could make use of this to execute beyond the granted permission. Thus,
+ * the driver must always check whether the model cache is corrupted before
+ * preparing the model from cache.
+ *
+ * getNumberOfCacheFilesNeeded returns how many of each type of cache files the driver
+ * implementation needs to cache a single prepared model. Returning 0 for both types
+ * indicates compilation caching is not supported by this driver. The driver may
+ * still choose not to cache certain compiled models even if it reports that caching
+ * is supported.
+ *
+ * If the device reports that caching is not supported, the user may avoid calling
+ * IDevice::prepareModelFromCache or providing cache file descriptors to
+ * IDevice::prepareModel_1_2.
*
* @return status Error status of the call, must be:
* - NONE if successful
* - DEVICE_UNAVAILABLE if driver is offline or busy
* - GENERAL_FAILURE if there is an unspecified error
- * @return supported A boolean indicating whether the driver supports compilation
- * caching. Even on returning true, the driver may still choose
- * not to cache certain compiled models.
+ * @return numModelCache An unsigned integer indicating how many files for model cache
+ * the driver needs to cache a single prepared model. It must
+ * be less than or equal to Constant::MAX_NUMBER_OF_CACHE_FILES.
+ * @return numDataCache An unsigned integer indicating how many files for data cache
+ * the driver needs to cache a single prepared model. It must
+ * be less than or equal to Constant::MAX_NUMBER_OF_CACHE_FILES.
*/
- isCachingSupported() generates (ErrorStatus status, bool supported);
+ getNumberOfCacheFilesNeeded()
+ generates (ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache);
/**
- * Creates a prepared model for execution.
+ * Asynchronously creates a prepared model for execution and optionally saves it
+ * into cache files.
*
- * prepareModel is used to make any necessary transformations or alternative
+ * prepareModel is used to make any necessary transformations to or alternative
* representations to a model for execution, possibly including
* transformations on the constant data, optimization on the model's graph,
* or compilation into the device's native binary format. The model itself
* is not changed.
*
+ * Optionally, caching information may be provided for the driver to save
+ * the prepared model to cache files for faster model compilation time
+ * when the same model preparation is requested in the future. There are
+ * two types of cache file handles provided to the driver: model cache
+ * and data cache. For more information on the two types of cache handles,
+ * refer to getNumberOfCacheFilesNeeded.
+ *
+ * The file descriptors must be opened with read and write permission. A file may
+ * have any size, and the corresponding file descriptor may have any offset. The
+ * driver must truncate a file to zero size before writing to that file. The file
+ * descriptors may be closed by the client once the asynchronous preparation has
+ * finished. The driver must dup a file descriptor if it wants to get access to
+ * the cache file later.
+ *
* The model is prepared asynchronously with respect to the caller. The
- * prepareModel function must verify the inputs to the prepareModel function
- * are correct. If there is an error, prepareModel must immediately invoke
+ * prepareModel function must verify the inputs to the preparedModel function
+ * related to preparing the model (as opposed to saving the prepared model to
+ * cache) are correct. If there is an error, prepareModel must immediately invoke
* the callback with the appropriate ErrorStatus value and nullptr for the
- * IPreparedModel, then return with the same ErrorStatus. If the inputs to
- * the prepareModel function are valid and there is no error, prepareModel
- * must launch an asynchronous task to prepare the model in the background,
- * and immediately return from prepareModel with ErrorStatus::NONE. If the
- * asynchronous task fails to launch, prepareModel must immediately invoke
- * the callback with ErrorStatus::GENERAL_FAILURE and nullptr for the
- * IPreparedModel, then return with ErrorStatus::GENERAL_FAILURE.
+ * IPreparedModel, then return with the same ErrorStatus. If the inputs to the
+ * prepareModel function that are related to preparing the model are valid and
+ * there is no error, prepareModel must launch an asynchronous task
+ * to prepare the model in the background, and immediately return from
+ * prepareModel with ErrorStatus::NONE. If the asynchronous task fails to launch,
+ * prepareModel must immediately invoke the callback with
+ * ErrorStatus::GENERAL_FAILURE and nullptr for the IPreparedModel, then return
+ * with ErrorStatus::GENERAL_FAILURE.
*
* When the asynchronous task has finished preparing the model, it must
* immediately invoke the callback function provided as an input to
@@ -160,6 +199,14 @@
* the callback object must be invoked with the appropriate ErrorStatus
* value and nullptr for the IPreparedModel.
*
+ * Optionally, the driver may save the prepared model to cache during the
+ * asynchronous preparation. Any error that occurs when saving to cache must
+ * not affect the status of preparing the model. Even if the input arguments
+ * related to the cache may be invalid, or the driver may fail to save to cache,
+ * the prepareModel function must finish preparing the model. The driver
+ * may choose not to save to cache even if the caching information is
+ * provided and valid.
+ *
* The only information that may be unknown to the model at this stage is
* the shape of the tensors, which may only be known at execution time. As
* such, some driver services may return partially prepared models, where
@@ -173,6 +220,26 @@
* @param model The model to be prepared for execution.
* @param preference Indicates the intended execution behavior of a prepared
* model.
+ * @param modelCache A vector of handles with each entry holding exactly one
+ * cache file descriptor for the security-sensitive cache. The length of
+ * the vector must either be 0 indicating that caching information is not provided,
+ * or match the numModelCache returned from getNumberOfCacheFilesNeeded. The cache
+ * handles will be provided in the same order when retrieving the
+ * preparedModel from cache files with prepareModelFromCache.
+ * @param dataCache A vector of handles with each entry holding exactly one
+ * cache file descriptor for the constants' cache. The length of
+ * the vector must either be 0 indicating that caching information is not provided,
+ * or match the numDataCache returned from getNumberOfCacheFilesNeeded. The cache
+ * handles will be provided in the same order when retrieving the
+ * preparedModel from cache files with prepareModelFromCache.
+ * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
+ * identifying the prepared model. The same token will be provided when retrieving
+ * the prepared model from the cache files with prepareModelFromCache.
+ * Tokens should be chosen to have a low rate of collision for a particular
+ * application. The driver cannot detect a collision; a collision will result
+ * in a failed execution or in a successful execution that produces incorrect
+ * output values. If both modelCache and dataCache are empty indicating that
+ * caching information is not provided, this token must be ignored.
* @param callback A callback object used to return the error status of
* preparing the model for execution and the prepared model if
* successful, nullptr otherwise. The callback object's notify function
@@ -182,9 +249,12 @@
* - NONE if preparation task is successfully launched
* - DEVICE_UNAVAILABLE if driver is offline or busy
* - GENERAL_FAILURE if there is an unspecified error
- * - INVALID_ARGUMENT if one of the input arguments is invalid
+ * - INVALID_ARGUMENT if one of the input arguments related to preparing the
+ * model is invalid
*/
prepareModel_1_2(Model model, ExecutionPreference preference,
+ vec<handle> modelCache, vec<handle> dataCache,
+ uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token,
IPreparedModelCallback callback)
generates (ErrorStatus status);
@@ -192,22 +262,17 @@
* Creates a prepared model from cache files for execution.
*
* prepareModelFromCache is used to retrieve a prepared model directly from
- * cache files to avoid slow model compilation time. There are exactly two
- * cache file descriptors provided to the driver: modelCache and dataCache.
+ * cache files to avoid slow model compilation time. There are
+ * two types of cache file handles provided to the driver: model cache
+ * and data cache. For more information on the two types of cache handles,
+ * refer to getNumberOfCacheFilesNeeded.
*
- * The dataCache is for caching constant data, possibly including preprocessed
- * and transformed tensor buffers. Any modification to the dataCache should
- * have no worse effect than generating bad output values at execution time.
- *
- * The modelCache is for caching security-sensitive data such as compiled
- * executable machine code in the device's native binary format. A modification
- * to the modelCache may affect the driver's execution behavior, and a malicious
- * client could make use of this to execute beyond the granted permission. Thus,
- * the driver must always check whether the modelCache is corrupted before preparing
- * the model from cache.
- *
- * The two file descriptors may be closed by the client once the asynchronous
- * preparation has finished. The driver has to copy all the data it needs.
+ * The file descriptors must be opened with read and write permission. A file may
+ * have any size, and the corresponding file descriptor may have any offset. The
+ * driver must truncate a file to zero size before writing to that file. The file
+ * descriptors may be closed by the client once the asynchronous preparation has
+ * finished. The driver must dup a file descriptor if it wants to get access to
+ * the cache file later.
*
* The model is prepared asynchronously with respect to the caller. The
* prepareModelFromCache function must verify the inputs to the
@@ -241,13 +306,17 @@
* used with different shapes of inputs on different (possibly concurrent)
* executions.
*
- * @param modelCache A handle holding exactly one cache file descriptor for the
- * security-sensitive cache.
- * @param dataCache A handle holding exactly one cache file descriptor for the
- * constants' cache.
+ * @param modelCache A vector of handles with each entry holding exactly one
+ * cache file descriptor for the security-sensitive cache. The length of
+ * the vector must match the numModelCache returned from getNumberOfCacheFilesNeeded.
+ * The cache handles will be provided in the same order as with prepareModel_1_2.
+ * @param dataCache A vector of handles with each entry holding exactly one
+ * cache file descriptor for the constants' cache. The length of the vector
+ * must match the numDataCache returned from getNumberOfCacheFilesNeeded.
+ * The cache handles will be provided in the same order as with prepareModel_1_2.
* @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
* identifying the prepared model. It is the same token provided when saving
- * the cache files with IPreparedModel::saveToCache. Tokens should be chosen
+ * the cache files with prepareModel_1_2. Tokens should be chosen
* to have a low rate of collision for a particular application. The driver
* cannot detect a collision; a collision will result in a failed execution
* or in a successful execution that produces incorrect output values.
@@ -263,7 +332,7 @@
* unspecified error
* - INVALID_ARGUMENT if one of the input arguments is invalid
*/
- prepareModelFromCache(handle modelCache, handle dataCache,
+ prepareModelFromCache(vec<handle> modelCache, vec<handle> dataCache,
uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token,
IPreparedModelCallback callback)
generates (ErrorStatus status);
diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal
index 757d5f1..5d2d80f 100644
--- a/neuralnetworks/1.2/IPreparedModel.hal
+++ b/neuralnetworks/1.2/IPreparedModel.hal
@@ -157,62 +157,4 @@
fmq_sync<FmqRequestDatum> requestChannel,
fmq_sync<FmqResultDatum> resultChannel)
generates (ErrorStatus status, IBurstContext context);
-
- /*
- * Saves the prepared model to cache files.
- *
- * saveToCache is used to save a prepared model to cache files for faster
- * model compilation time when the same model preparation is requested in
- * the future. There are exactly two cache file descriptors provided to the
- * driver: modelCache and dataCache.
- *
- * The dataCache is for caching constant data, possibly including preprocessed
- * and transformed tensor buffers. Any modification to the dataCache should
- * have no worse effect than generating bad output values at execution time.
- *
- * The modelCache is for caching security-sensitive data such as compiled
- * executable machine code in the device's native binary format. A modification
- * to the modelCache may affect the driver's execution behavior, and a malicious
- * client could make use of this to execute beyond the granted permission. Thus,
- * the driver must always check whether the modelCache is corrupted before preparing
- * the model from cache.
- *
- * The two file descriptors must point to two zero-length files with offset
- * positioned at the beginning of the file. The file descriptors may be closed
- * by the client once the method has returned.
- *
- * If the driver decides not to save the prepared model without looking at the
- * input arguments to the saveToCache function, saveToCache must return with
- * ErrorStatus::GENERAL_FAILURE. Otherwise, the saveToCache function must verify
- * the input arguments to the saveToCache function are valid, and return with
- * ErrorStatus::INVALID_ARGUMENT if not. If the inputs are valid but the driver
- * could not save the prepared model, saveToCache must return with the appropriate
- * ErrorStatus. Otherwise, it must write the cache files and return
- * ErrorStatus::NONE. Unless saveToCache returns ErrorStatus::NONE, the contents
- * of the cache files are undefined.
- *
- * @param modelCache A handle holding exactly one cache file descriptor for the
- * security-sensitive cache.
- * @param dataCache A handle holding exactly one cache file descriptor for the
- * constants' cache.
- * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
- * identifying the prepared model. The same token will be provided
- * when retrieving the prepared model from cache files with
- * IDevice::prepareModelFromCache. Tokens should be chosen to have
- * a low rate of collision for a particular application. The driver
- * cannot detect a collision; a collision will result in a failed
- * execution or in a successful execution that produces incorrect
- * output values.
- * @return status Error status of saveToCache, must be:
- * - NONE if saveToCache is performed successfully
- * - DEVICE_UNAVAILABLE if driver is offline or busy
- * - GENERAL_FAILURE if the driver could not save the
- * prepared model or if there is an unspecified error
- * - INVALID_ARGUMENT if one of the input arguments is invalid,
- * unless the driver decides not to save the prepared model
- * without looking at the input arguments
- */
- saveToCache(handle modelCache, handle dataCache,
- uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token)
- generates (ErrorStatus status);
};
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index bb14dec..28d0119 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -30,6 +30,11 @@
* The byte size of the cache token.
*/
BYTE_SIZE_OF_CACHE_TOKEN = 32,
+
+ /**
+ * The maximum number of files for each type of cache in compilation caching.
+ */
+ MAX_NUMBER_OF_CACHE_FILES = 32,
};
enum OperandType : @1.0::OperandType {
@@ -450,11 +455,10 @@
*
* Outputs:
* * 0: The output 4-D tensor, of shape
- * [batches, out_height, out_width, depth_out]. For output tensor of
- * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
- * must be satisfied: output_scale > input_scale * filter_scale (for
- * filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
- * this condition must be true for all filter scales).
+ * [batches, out_height, out_width, depth_out]. Before API level 29,
+ * for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the
+ * following condition must be satisfied:
+ * output_scale > input_scale * filter_scale
*
* Available since API level 27.
*/
@@ -600,11 +604,10 @@
*
* Outputs:
* * 0: The output 4-D tensor, of shape
- * [batches, out_height, out_width, depth_out]. For output tensor of
- * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
- * must be satisfied: output_scale > input_scale * filter_scale (for
- * filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
- * this condition must be true for all filter scales).
+ * [batches, out_height, out_width, depth_out]. Before API level 29,
+ * for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the
+ * following condition must be satisfied:
+ * output_scale > input_scale * filter_scale
*
* Available since API level 27.
*/
@@ -780,10 +783,10 @@
* invoke on the result.
*
* Outputs:
- * * 0: The output tensor, of shape [batch_size, num_units]. For output
- * tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
- * condition must be satisfied:
- * output_scale > input_scale * filter_scale.
+ * * 0: The output tensor, of shape [batch_size, num_units]. Before API
+ * level 29, For output tensor of {@link
+ * OperandType::TENSOR_QUANT8_ASYMM}, the following condition must be
+ * satisfied: output_scale > input_scale * filter_scale.
*
* Available since API level 27.
*/
@@ -1979,7 +1982,8 @@
* must be >= 1.
* * 2: A 2-D Tensor of {@link OperandType::TENSOR_INT32}, the paddings
* for each spatial dimension of the input tensor. All values must be
- * >= 0. The shape of the tensor must be {rank(input0), 2}.
+ * >= 0. The shape of the tensor must be {M, 2}, where M is the number
+ * of spatial dimensions.
* padding[i, 0] specifies the number of element to be padded in the
* front of dimension i.
* padding[i, 1] specifies the number of element to be padded after the
@@ -2271,113 +2275,113 @@
* Inputs:
* * 0: The input.
* A 3-D tensor of shape:
- * If time-major: [max_time, batch_size, output_size]
- * If batch-major: [batch_size, max_time, output_size]
+ * If time-major: [max_time, batch_size, input_size]
+ * If batch-major: [batch_size, max_time, input_size]
* where "max_time" is the number of timesteps (sequence length),
* "batch_size" corresponds to the batching dimension, and
* "input_size" is the size of the input.
* * 1: The forward input-to-input weights. Optional.
- * A 2-D tensor of shape [num_units, input_size], where “num_units”
- * corresponds to the number of cell units.
+ * A 2-D tensor of shape [fw_num_units, input_size], where “fw_num_units”
+ * corresponds to the number of forward cell units.
* * 2: The forward input-to-forget weights.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [fw_num_units, input_size].
* * 3: The forward input-to-cell weights.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [fw_num_units, input_size].
* * 4: The forward input-to-output weights.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [fw_num_units, input_size].
* * 5: The forward recurrent-to-input weights. Optional.
- * A 2-D tensor of shape [num_units, output_size], where “output_size”
- * corresponds to either the number of cell units (i.e., “num_units”),
- * or the second dimension of the “projection_weights”, if defined.
+ * A 2-D tensor of shape [fw_num_units, fw_output_size], where “fw_output_size”
+ * corresponds to either the number of cell units (i.e., fw_num_units),
+ * or the second dimension of the “fw_projection_weights”, if defined.
* * 6: The forward recurrent-to-forget weights.
- * A 2-D tensor of shape [num_units, output_size].
+ * A 2-D tensor of shape [fw_num_units, fw_output_size].
* * 7: The forward recurrent-to-cell weights.
- * A 2-D tensor of shape [num_units, output_size].
+ * A 2-D tensor of shape [fw_num_units, fw_output_size].
* * 8: The forward recurrent-to-output weights.
- * A 2-D tensor of shape [num_units, output_size].
+ * A 2-D tensor of shape [fw_num_units, fw_output_size].
* * 9: The forward cell-to-input weights. Optional.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [fw_num_units].
* * 10: The forward cell-to-forget weights. Optional.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [fw_num_units].
* * 11: The forward cell-to-output weights. Optional.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [fw_num_units].
* * 12: The forward input gate bias. Optional.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [fw_num_units].
* * 13: The forward forget gate bias.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [fw_num_units].
* * 14: The forward cell gate bias.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [fw_num_units].
* * 15: The forward output gate bias.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [fw_num_units].
* * 16: The forward projection weights. Optional.
- * A 2-D tensor of shape [output_size, num_units].
+ * A 2-D tensor of shape [fw_output_size, fw_num_units].
* * 17: The forward projection bias. Optional.
- * A 1-D tensor of shape [output_size].
+ * A 1-D tensor of shape [fw_output_size].
* * 18: The backward input-to-input weights. Optional.
- * A 2-D tensor of shape [num_units, input_size], where “num_units”
- * corresponds to the number of cell units.
+ * A 2-D tensor of shape [bw_num_units, input_size], where “bw_num_units”
+ * corresponds to the number of backward cell units.
* * 19: The backward input-to-forget weights.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [bw_num_units, input_size].
* * 20: The backward input-to-cell weights.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [bw_num_units, input_size].
* * 21: The backward input-to-output weights.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [bw_num_units, input_size].
* * 22: The backward recurrent-to-input weights. Optional.
- * A 2-D tensor of shape [num_units, output_size], where “output_size”
- * corresponds to either the number of cell units (i.e., “num_units”),
- * or the second dimension of the “projection_weights”, if defined.
+ * A 2-D tensor of shape [bw_num_units, bw_output_size], where “bw_output_size”
+ * corresponds to either the number of cell units (i.e., “bw_num_units”),
+ * or the second dimension of the “bw_projection_weights”, if defined.
* * 23: The backward recurrent-to-forget weights.
- * A 2-D tensor of shape [num_units, output_size].
+ * A 2-D tensor of shape [bw_num_units, bw_output_size].
* * 24: The backward recurrent-to-cell weights.
- * A 2-D tensor of shape [num_units, output_size].
+ * A 2-D tensor of shape [bw_num_units, bw_output_size].
* * 25: The backward recurrent-to-output weights.
- * A 2-D tensor of shape [num_units, output_size].
+ * A 2-D tensor of shape [bw_num_units, bw_output_size].
* * 26: The backward cell-to-input weights. Optional.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [bw_num_units].
* * 27: The backward cell-to-forget weights. Optional.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [bw_num_units].
* * 28: The backward cell-to-output weights. Optional.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [bw_num_units].
* * 29: The backward input gate bias. Optional.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [bw_num_units].
* * 30: The backward forget gate bias.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [bw_num_units].
* * 31: The backward cell gate bias.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [bw_num_units].
* * 32: The backward output gate bias.
- * A 1-D tensor of shape [num_units].
+ * A 1-D tensor of shape [bw_num_units].
* * 33: The backward projection weights. Optional.
- * A 2-D tensor of shape [output_size, num_units].
+ * A 2-D tensor of shape [bw_output_size, bw_num_units].
* * 34: The backward projection bias. Optional.
- * A 1-D tensor of shape [output_size].
+ * A 1-D tensor of shape [bw_output_size].
* * 35: The forward input activation state.
- * A 2-D tensor of shape [batch_size, output_size].
+ * A 2-D tensor of shape [batch_size, bw_output_size].
* * 36: The forward input cell state.
- * A 2-D tensor of shape [batch_size, num_units].
+ * A 2-D tensor of shape [batch_size, bw_num_units].
* * 37: The backward input activation state.
- * A 2-D tensor of shape [batch_size, output_size].
+ * A 2-D tensor of shape [batch_size, bw_output_size].
* * 38: The backward input cell state.
- * A 2-D tensor of shape [batch_size, num_units].
+ * A 2-D tensor of shape [batch_size, bw_num_units].
* * 39: The auxiliary input. Optional.
* A 3-D tensor of shape [max_time, batch_size, input_size], where “batch_size”
* corresponds to the batching dimension, and “input_size” is the size
* of the input.
* * 40: The forward auxiliary input-to-input weights. Optional.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [fw_num_units, input_size].
* * 41: The forward auxiliary input-to-forget weights. Optional.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [fw_num_units, input_size].
* * 42: The forward auxiliary input-to-cell weights. Optional.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [fw_num_units, input_size].
* * 43: The forward auxiliary input-to-output weights. Optional.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [fw_num_units, input_size].
* * 44: The backward auxiliary input-to-input weights. Optional.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [bw_num_units, input_size].
* * 45: The backward auxiliary input-to-forget weights. Optional.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [bw_num_units, input_size].
* * 46: The backward auxiliary input-to-cell weights. Optional.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [bw_num_units, input_size].
* * 47: The backward auxiliary input-to-output weights. Optional.
- * A 2-D tensor of shape [num_units, input_size].
+ * A 2-D tensor of shape [bw_num_units, input_size].
* * 48: The activation function.
* A value indicating the activation function:
* <ul>
@@ -2409,16 +2413,46 @@
* * 52: time_major
* An {@link OperandType::BOOL} scalar specifying the shape format
* of input and output tensors.
+ * * 53: The forward input layer normalization weights. Optional.
+ * A 1-D tensor of shape [fw_num_units]. Used to rescale normalized inputs
+ * to activation at input gate.
+ * * 54: The forward forget layer normalization weights. Optional.
+ * A 1-D tensor of shape [fw_num_units]. Used to rescale normalized inputs
+ * to activation at forget gate.
+ * * 55: The forward cell layer normalization weights. Optional.
+ * A 1-D tensor of shape [fw_num_units]. Used to rescale normalized inputs
+ * to activation at cell gate.
+ * * 56: The forward output layer normalization weights. Optional.
+ * A 1-D tensor of shape [fw_num_units]. Used to rescale normalized inputs
+ * to activation at output gate.
+ * * 57: The backward input layer normalization weights. Optional.
+ * A 1-D tensor of shape [bw_num_units]. Used to rescale normalized inputs
+ * to activation at input gate.
+ * * 58: The backward forget layer normalization weights. Optional.
+ * A 1-D tensor of shape [bw_num_units]. Used to rescale normalized inputs
+ * to activation at forget gate.
+ * * 59: The backward cell layer normalization weights. Optional.
+ * A 1-D tensor of shape [bw_num_units]. Used to rescale normalized inputs
+ * to activation at cell gate.
+ * * 60: The backward output layer normalization weights. Optional.
+ * A 1-D tensor of shape [bw_num_units]. Used to rescale normalized inputs
+ * to activation at output gate.
*
* Outputs:
* * 0: The forward output.
* A 3-D tensor of shape:
- * If time-major: [max_time, batch_size, output_size]
- * If batch-major: [batch_size, max_time, output_size]
+ * If time-major and not merge_outputs:
+ * [max_time, batch_size, fw_output_size]
+ * If time-major and merge_outputs:
+ * [max_time, batch_size, fw_output_size + bw_output_size]
+ * If batch-major and not merge_outputs:
+ * [batch_size, max_time, fw_output_size]
+ * If batch-major and merge_outputs:
+ * [batch_size, max_time, fw_output_size + bw_output_size]
* * 1: The backward output. Unused if merge_outputs is true.
* A 3-D tensor of shape:
- * If time-major: [max_time, batch_size, output_size]
- * If batch-major: [batch_size, max_time, output_size]
+ * If time-major: [max_time, batch_size, bw_output_size]
+ * If batch-major: [batch_size, max_time, bw_output_size]
*
* Available since API level 29.
*/
@@ -3121,11 +3155,7 @@
*
* Outputs:
* * 0: The output 4-D tensor, of shape
- * [batches, out_height, out_width, depth_out]. For output tensor of
- * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
- * must be satisfied: output_scale > input_scale * filter_scale (for
- * filter tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
- * this condition must be true for all filter scales).
+ * [batches, out_height, out_width, depth_out].
*
* Available since API level 29.
*/
@@ -4330,11 +4360,7 @@
*
* Outputs:
* * 0: The output 4-D tensor, of shape
- * [batches, out_height, out_width, depth_out]. For output tensor of
- * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
- * must be satisfied: output_scale > input_scale * filter_scale (for
- * filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
- * this condition must be true for all filter scales).
+ * [batches, out_height, out_width, depth_out].
*
* Available since API level 29.
*/
@@ -4366,9 +4392,9 @@
* Inputs:
* * 0: The input (\f$x_t\f$).
* A 3-D tensor of shape:
- * If time-major: [max_time, batch_size, output_size]
- * If batch-major: [batch_size, max_time, output_size]
- * where “max_size” is the number of timesteps (sequence length),
+ * If time-major: [max_time, batch_size, input_size]
+ * If batch-major: [batch_size, max_time, input_size]
+ * where “max_time” is the number of timesteps (sequence length),
* “batch_size” corresponds to the batching dimension, and
* “input_size” is the size of the input.
* * 1: The input-to-input weights (\f$W_{xi}\f$). Optional.
@@ -4428,16 +4454,16 @@
* projection layer, such that values are bound within
* [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled.
* * 23:Time-major if true, batch-major if false.
- * * 24:The input layer normalization weights.
+ * * 24:The input layer normalization weights. Optional.
* A 1-D tensor of shape [num_units]. Used to rescale normalized inputs
* to activation at input gate.
- * * 25:The forget layer normalization weights.
+ * * 25:The forget layer normalization weights. Optional.
* A 1-D tensor of shape [num_units]. Used to rescale normalized inputs
* to activation at forget gate.
- * * 26:The cell layer normalization weights.
+ * * 26:The cell layer normalization weights. Optional.
* A 1-D tensor of shape [num_units]. Used to rescale normalized inputs
* to activation at cell gate.
- * * 27:The output layer normalization weights.
+ * * 27:The output layer normalization weights. Optional.
* A 1-D tensor of shape [num_units]. Used to rescale normalized inputs
* to activation at output gate.
*
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index 365a750..6fb16c2 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -77,10 +77,15 @@
EXPECT_TRUE(ret.isOk());
}
-// isCachingSupported test
-TEST_F(NeuralnetworksHidlTest, IsCachingSupported) {
- Return<void> ret = device->isCachingSupported(
- [](ErrorStatus status, bool) { EXPECT_EQ(ErrorStatus::NONE, status); });
+// getNumberOfCacheFilesNeeded test
+TEST_F(NeuralnetworksHidlTest, getNumberOfCacheFilesNeeded) {
+ Return<void> ret = device->getNumberOfCacheFilesNeeded(
+ [](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) {
+ EXPECT_EQ(ErrorStatus::NONE, status);
+ EXPECT_LE(numModelCache,
+ static_cast<uint32_t>(Constant::MAX_NUMBER_OF_CACHE_FILES));
+ EXPECT_LE(numDataCache, static_cast<uint32_t>(Constant::MAX_NUMBER_OF_CACHE_FILES));
+ });
EXPECT_TRUE(ret.isOk());
}
} // namespace functional
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 00989e5..167fc09 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -54,29 +54,39 @@
[[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape;
[[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape;
-enum class AccessMode { READ_ONLY, WRITE_ONLY };
+enum class AccessMode { READ_WRITE, READ_ONLY, WRITE_ONLY };
-void createCacheHandle(const std::vector<std::string>& files, AccessMode mode,
- hidl_handle* handle) {
- std::vector<int> fds;
- for (const auto& file : files) {
- int fd;
- if (mode == AccessMode::READ_ONLY) {
- fd = open(file.c_str(), O_RDONLY);
- } else if (mode == AccessMode::WRITE_ONLY) {
- fd = open(file.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
- } else {
- FAIL();
+// Creates cache handles based on provided file groups.
+// The outer vector corresponds to handles and the inner vector is for fds held by each handle.
+void createCacheHandles(const std::vector<std::vector<std::string>>& fileGroups,
+ const std::vector<AccessMode>& mode, hidl_vec<hidl_handle>* handles) {
+ handles->resize(fileGroups.size());
+ for (uint32_t i = 0; i < fileGroups.size(); i++) {
+ std::vector<int> fds;
+ for (const auto& file : fileGroups[i]) {
+ int fd;
+ if (mode[i] == AccessMode::READ_ONLY) {
+ fd = open(file.c_str(), O_RDONLY);
+ } else if (mode[i] == AccessMode::WRITE_ONLY) {
+ fd = open(file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ } else if (mode[i] == AccessMode::READ_WRITE) {
+ fd = open(file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ } else {
+ FAIL();
+ }
+ ASSERT_GE(fd, 0);
+ fds.push_back(fd);
}
- ASSERT_GE(fd, 0);
- fds.push_back(fd);
+ native_handle_t* cacheNativeHandle = native_handle_create(fds.size(), 0);
+ ASSERT_NE(cacheNativeHandle, nullptr);
+ std::copy(fds.begin(), fds.end(), &cacheNativeHandle->data[0]);
+ (*handles)[i].setTo(cacheNativeHandle, /*shouldOwn=*/true);
}
- native_handle_t* cacheNativeHandle = native_handle_create(fds.size(), 0);
- ASSERT_NE(cacheNativeHandle, nullptr);
- for (uint32_t i = 0; i < fds.size(); i++) {
- cacheNativeHandle->data[i] = fds[i];
- }
- handle->setTo(cacheNativeHandle, /*shouldOwn=*/true);
+}
+
+void createCacheHandles(const std::vector<std::vector<std::string>>& fileGroups, AccessMode mode,
+ hidl_vec<hidl_handle>* handles) {
+ createCacheHandles(fileGroups, std::vector<AccessMode>(fileGroups.size(), mode), handles);
}
} // namespace
@@ -88,38 +98,43 @@
NeuralnetworksHidlTest::SetUp();
ASSERT_NE(device.get(), nullptr);
- // Create cache directory. The cache directory and cache files are always created to test
- // the behavior of prepareModelFromCache, even when caching is not supported.
+ // Create cache directory. The cache directory and a temporary cache file is always created
+ // to test the behavior of prepareModelFromCache, even when caching is not supported.
char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX";
char* cacheDir = mkdtemp(cacheDirTemp);
ASSERT_NE(cacheDir, nullptr);
mCacheDir = cacheDir;
+ mCacheDir.push_back('/');
- // Create empty cache files.
- mCache1 = mCacheDir + "/cache1";
- mCache2 = mCacheDir + "/cache2";
- mCache3 = mCacheDir + "/cache3";
- // A dummy handle, use AccessMode::WRITE_ONLY for createCacheHandle to create files.
- hidl_handle handle;
- createCacheHandle({mCache1, mCache2, mCache3}, AccessMode::WRITE_ONLY, &handle);
-
- // Check if caching is supported.
- bool isCachingSupported;
- Return<void> ret = device->isCachingSupported(
- [&isCachingSupported](ErrorStatus status, bool supported) {
+ Return<void> ret = device->getNumberOfCacheFilesNeeded(
+ [this](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) {
EXPECT_EQ(ErrorStatus::NONE, status);
- isCachingSupported = supported;
+ mNumModelCache = numModelCache;
+ mNumDataCache = numDataCache;
});
EXPECT_TRUE(ret.isOk());
- if (isCachingSupported) {
- mIsCachingSupported = true;
- } else {
+ mIsCachingSupported = mNumModelCache > 0 || mNumDataCache > 0;
+
+ // Create empty cache files.
+ mTmpCache = mCacheDir + "tmp";
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ mModelCache.push_back({mCacheDir + "model" + std::to_string(i)});
+ }
+ for (uint32_t i = 0; i < mNumDataCache; i++) {
+ mDataCache.push_back({mCacheDir + "data" + std::to_string(i)});
+ }
+ // Dummy handles, use AccessMode::WRITE_ONLY for createCacheHandles to create files.
+ hidl_vec<hidl_handle> modelHandle, dataHandle, tmpHandle;
+ createCacheHandles(mModelCache, AccessMode::WRITE_ONLY, &modelHandle);
+ createCacheHandles(mDataCache, AccessMode::WRITE_ONLY, &dataHandle);
+ createCacheHandles({{mTmpCache}}, AccessMode::WRITE_ONLY, &tmpHandle);
+
+ if (!mIsCachingSupported) {
LOG(INFO) << "NN VTS: Early termination of test because vendor service does not "
"support compilation caching.";
std::cout << "[ ] Early termination of test because vendor service does not "
"support compilation caching."
<< std::endl;
- mIsCachingSupported = false;
}
}
@@ -127,22 +142,49 @@
// The tmp directory is only removed when the driver reports caching not supported,
// otherwise it is kept for debugging purpose.
if (!mIsCachingSupported) {
- remove(mCache1.c_str());
- remove(mCache2.c_str());
- remove(mCache3.c_str());
+ remove(mTmpCache.c_str());
rmdir(mCacheDir.c_str());
}
NeuralnetworksHidlTest::TearDown();
}
- void saveModelToCache(sp<IPreparedModel> preparedModel, const hidl_handle& cache1,
- const hidl_handle& cache2, ErrorStatus* status) {
- // Save IPreparedModel to cache.
+ void saveModelToCache(const V1_2::Model& model, const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache, bool* supported,
+ sp<IPreparedModel>* preparedModel = nullptr) {
+ if (preparedModel != nullptr) *preparedModel = nullptr;
+
+ // See if service can handle model.
+ bool fullySupportsModel = false;
+ Return<void> supportedCall = device->getSupportedOperations_1_2(
+ model,
+ [&fullySupportsModel, &model](ErrorStatus status, const hidl_vec<bool>& supported) {
+ ASSERT_EQ(ErrorStatus::NONE, status);
+ ASSERT_EQ(supported.size(), model.operations.size());
+ fullySupportsModel = std::all_of(supported.begin(), supported.end(),
+ [](bool valid) { return valid; });
+ });
+ ASSERT_TRUE(supportedCall.isOk());
+ *supported = fullySupportsModel;
+ if (!fullySupportsModel) return;
+
+ // Launch prepare model.
+ sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+ ASSERT_NE(nullptr, preparedModelCallback.get());
hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
- Return<ErrorStatus> saveToCacheStatus =
- preparedModel->saveToCache(cache1, cache2, cacheToken);
- ASSERT_TRUE(saveToCacheStatus.isOk());
- *status = static_cast<ErrorStatus>(saveToCacheStatus);
+ Return<ErrorStatus> prepareLaunchStatus =
+ device->prepareModel_1_2(model, ExecutionPreference::FAST_SINGLE_ANSWER, modelCache,
+ dataCache, cacheToken, preparedModelCallback);
+ ASSERT_TRUE(prepareLaunchStatus.isOk());
+ ASSERT_EQ(static_cast<ErrorStatus>(prepareLaunchStatus), ErrorStatus::NONE);
+
+ // Retrieve prepared model.
+ preparedModelCallback->wait();
+ ASSERT_EQ(preparedModelCallback->getStatus(), ErrorStatus::NONE);
+ if (preparedModel != nullptr) {
+ *preparedModel =
+ V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
+ .withDefault(nullptr);
+ }
}
bool checkEarlyTermination(ErrorStatus status) {
@@ -157,14 +199,27 @@
return false;
}
- void prepareModelFromCache(const hidl_handle& cache1, const hidl_handle& cache2,
+ bool checkEarlyTermination(bool supported) {
+ if (!supported) {
+ LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+ "prepare model that it does not support.";
+ std::cout << "[ ] Early termination of test because vendor service cannot "
+ "prepare model that it does not support."
+ << std::endl;
+ return true;
+ }
+ return false;
+ }
+
+ void prepareModelFromCache(const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache,
sp<IPreparedModel>* preparedModel, ErrorStatus* status) {
// Launch prepare model from cache.
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
ASSERT_NE(nullptr, preparedModelCallback.get());
hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
- Return<ErrorStatus> prepareLaunchStatus =
- device->prepareModelFromCache(cache1, cache2, cacheToken, preparedModelCallback);
+ Return<ErrorStatus> prepareLaunchStatus = device->prepareModelFromCache(
+ modelCache, dataCache, cacheToken, preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
if (static_cast<ErrorStatus>(prepareLaunchStatus) != ErrorStatus::NONE) {
*preparedModel = nullptr;
@@ -179,49 +234,54 @@
.withDefault(nullptr);
}
+ // Absolute path to the temporary cache directory.
std::string mCacheDir;
- std::string mCache1;
- std::string mCache2;
- std::string mCache3;
+
+ // Groups of file paths for model and data cache in the tmp cache directory, initialized with
+ // outer_size = mNum{Model|Data}Cache, inner_size = 1. The outer vector corresponds to handles
+ // and the inner vector is for fds held by each handle.
+ std::vector<std::vector<std::string>> mModelCache;
+ std::vector<std::vector<std::string>> mDataCache;
+
+ // A separate temporary file path in the tmp cache directory.
+ std::string mTmpCache;
+
uint8_t mToken[static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)] = {};
- bool mIsCachingSupported;
+ uint32_t mNumModelCache;
+ uint32_t mNumDataCache;
+ uint32_t mIsCachingSupported;
};
TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) {
// Create test HIDL model and compile.
Model testModel = createTestModel();
sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
// Save the compilation to cache.
{
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (!mIsCachingSupported) {
- EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- } else {
- if (checkEarlyTermination(status)) return;
- ASSERT_EQ(status, ErrorStatus::NONE);
- }
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ saveModelToCache(testModel, modelCache, dataCache, &supported);
+ if (checkEarlyTermination(supported)) return;
}
// Retrieve preparedModel from cache.
{
preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
if (!mIsCachingSupported) {
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
return;
+ } else if (checkEarlyTermination(status)) {
+ ASSERT_EQ(preparedModel, nullptr);
+ return;
} else {
ASSERT_EQ(status, ErrorStatus::NONE);
ASSERT_NE(preparedModel, nullptr);
@@ -238,41 +298,54 @@
// Create test HIDL model and compile.
Model testModel = createTestModel();
sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
// Save the compilation to cache.
{
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (!mIsCachingSupported) {
- EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- } else {
- if (checkEarlyTermination(status)) return;
- ASSERT_EQ(status, ErrorStatus::NONE);
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ uint8_t dummyBytes[] = {0, 0};
+ // Write a dummy integer to the cache.
+ // The driver should be able to handle non-empty cache and non-zero fd offset.
+ for (uint32_t i = 0; i < modelCache.size(); i++) {
+ ASSERT_EQ(write(modelCache[i].getNativeHandle()->data[0], &dummyBytes,
+ sizeof(dummyBytes)),
+ sizeof(dummyBytes));
}
+ for (uint32_t i = 0; i < dataCache.size(); i++) {
+ ASSERT_EQ(
+ write(dataCache[i].getNativeHandle()->data[0], &dummyBytes, sizeof(dummyBytes)),
+ sizeof(dummyBytes));
+ }
+ saveModelToCache(testModel, modelCache, dataCache, &supported);
+ if (checkEarlyTermination(supported)) return;
}
// Retrieve preparedModel from cache.
{
preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
uint8_t dummyByte = 0;
- // Advance offset by one byte.
- ASSERT_GE(read(cache1.getNativeHandle()->data[0], &dummyByte, 1), 0);
- ASSERT_GE(read(cache2.getNativeHandle()->data[0], &dummyByte, 1), 0);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ // Advance the offset of each handle by one byte.
+ // The driver should be able to handle non-zero fd offset.
+ for (uint32_t i = 0; i < modelCache.size(); i++) {
+ ASSERT_GE(read(modelCache[i].getNativeHandle()->data[0], &dummyByte, 1), 0);
+ }
+ for (uint32_t i = 0; i < dataCache.size(); i++) {
+ ASSERT_GE(read(dataCache[i].getNativeHandle()->data[0], &dummyByte, 1), 0);
+ }
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
if (!mIsCachingSupported) {
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
return;
+ } else if (checkEarlyTermination(status)) {
+ ASSERT_EQ(preparedModel, nullptr);
+ return;
} else {
ASSERT_EQ(status, ErrorStatus::NONE);
ASSERT_NE(preparedModel, nullptr);
@@ -285,234 +358,512 @@
/*testDynamicOutputShape=*/false);
}
+TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+
+ // Test with number of model cache files greater than mNumModelCache.
+ {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ // Pass an additional cache file for model cache.
+ mModelCache.push_back({mTmpCache});
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mModelCache.pop_back();
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
+ ErrorStatus status;
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Test with number of model cache files smaller than mNumModelCache.
+ if (mModelCache.size() > 0) {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ // Pop out the last cache file.
+ auto tmp = mModelCache.back();
+ mModelCache.pop_back();
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mModelCache.push_back(tmp);
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
+ ErrorStatus status;
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Test with number of data cache files greater than mNumDataCache.
+ {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ // Pass an additional cache file for data cache.
+ mDataCache.push_back({mTmpCache});
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mDataCache.pop_back();
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
+ ErrorStatus status;
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Test with number of data cache files smaller than mNumDataCache.
+ if (mDataCache.size() > 0) {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ // Pop out the last cache file.
+ auto tmp = mDataCache.back();
+ mDataCache.pop_back();
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mDataCache.push_back(tmp);
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
+ ErrorStatus status;
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+}
+
+TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) {
+ // Create test HIDL model and compile.
+ Model testModel = createTestModel();
+
+ // Save the compilation to cache.
+ {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ saveModelToCache(testModel, modelCache, dataCache, &supported);
+ if (checkEarlyTermination(supported)) return;
+ }
+
+ // Test with number of model cache files greater than mNumModelCache.
+ {
+ sp<IPreparedModel> preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ mModelCache.push_back({mTmpCache});
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mModelCache.pop_back();
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Test with number of model cache files smaller than mNumModelCache.
+ if (mModelCache.size() > 0) {
+ sp<IPreparedModel> preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ auto tmp = mModelCache.back();
+ mModelCache.pop_back();
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mModelCache.push_back(tmp);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Test with number of data cache files greater than mNumDataCache.
+ {
+ sp<IPreparedModel> preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ mDataCache.push_back({mTmpCache});
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mDataCache.pop_back();
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Test with number of data cache files smaller than mNumDataCache.
+ if (mDataCache.size() > 0) {
+ sp<IPreparedModel> preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ auto tmp = mDataCache.back();
+ mDataCache.pop_back();
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mDataCache.push_back(tmp);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+}
+
TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) {
// Create test HIDL model and compile.
Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
- // cache1 with invalid NumFd.
- {
+ // Go through each handle in model cache, test with NumFd greater than 1.
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ // Pass an invalid number of fds for handle i.
+ mModelCache[i].push_back(mTmpCache);
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mModelCache[i].pop_back();
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1, mCache3}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
}
+ ASSERT_EQ(preparedModel, nullptr);
}
- // cache2 with invalid NumFd.
- {
+ // Go through each handle in model cache, test with NumFd equal to 0.
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ // Pass an invalid number of fds for handle i.
+ auto tmp = mModelCache[i].back();
+ mModelCache[i].pop_back();
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mModelCache[i].push_back(tmp);
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2, mCache3}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
}
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Go through each handle in data cache, test with NumFd greater than 1.
+ for (uint32_t i = 0; i < mNumDataCache; i++) {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ // Pass an invalid number of fds for handle i.
+ mDataCache[i].push_back(mTmpCache);
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mDataCache[i].pop_back();
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
+ ErrorStatus status;
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Go through each handle in data cache, test with NumFd equal to 0.
+ for (uint32_t i = 0; i < mNumDataCache; i++) {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ // Pass an invalid number of fds for handle i.
+ auto tmp = mDataCache[i].back();
+ mDataCache[i].pop_back();
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mDataCache[i].push_back(tmp);
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
+ ErrorStatus status;
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
}
}
TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) {
// Create test HIDL model and compile.
Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
// Save the compilation to cache.
{
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::NONE);
- }
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ saveModelToCache(testModel, modelCache, dataCache, &supported);
+ if (checkEarlyTermination(supported)) return;
}
- // cache1 with invalid NumFd.
- {
- preparedModel = nullptr;
+ // Go through each handle in model cache, test with NumFd greater than 1.
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ sp<IPreparedModel> preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1, mCache3}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ mModelCache[i].push_back(mTmpCache);
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mModelCache[i].pop_back();
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
if (status != ErrorStatus::GENERAL_FAILURE) {
ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- ASSERT_EQ(preparedModel, nullptr);
}
+ ASSERT_EQ(preparedModel, nullptr);
}
- // cache2 with invalid NumFd.
- {
- preparedModel = nullptr;
+ // Go through each handle in model cache, test with NumFd equal to 0.
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ sp<IPreparedModel> preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2, mCache3}, AccessMode::READ_ONLY, &cache2);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ auto tmp = mModelCache[i].back();
+ mModelCache[i].pop_back();
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mModelCache[i].push_back(tmp);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
if (status != ErrorStatus::GENERAL_FAILURE) {
ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- ASSERT_EQ(preparedModel, nullptr);
}
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Go through each handle in data cache, test with NumFd greater than 1.
+ for (uint32_t i = 0; i < mNumDataCache; i++) {
+ sp<IPreparedModel> preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ mDataCache[i].push_back(mTmpCache);
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mDataCache[i].pop_back();
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+ }
+
+ // Go through each handle in data cache, test with NumFd equal to 0.
+ for (uint32_t i = 0; i < mNumDataCache; i++) {
+ sp<IPreparedModel> preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ auto tmp = mDataCache[i].back();
+ mDataCache[i].pop_back();
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ mDataCache[i].push_back(tmp);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
}
}
TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) {
// Create test HIDL model and compile.
Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
+ std::vector<AccessMode> modelCacheMode(mNumModelCache, AccessMode::READ_WRITE);
+ std::vector<AccessMode> dataCacheMode(mNumDataCache, AccessMode::READ_WRITE);
- // cache1 with invalid access mode.
- {
+ // Go through each handle in model cache, test with invalid access mode.
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ modelCacheMode[i] = AccessMode::READ_ONLY;
+ createCacheHandles(mModelCache, modelCacheMode, &modelCache);
+ createCacheHandles(mDataCache, dataCacheMode, &dataCache);
+ modelCacheMode[i] = AccessMode::READ_WRITE;
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
}
- // cache2 with invalid access mode.
- {
+ // Go through each handle in data cache, test with invalid access mode.
+ for (uint32_t i = 0; i < mNumDataCache; i++) {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ dataCacheMode[i] = AccessMode::READ_ONLY;
+ createCacheHandles(mModelCache, modelCacheMode, &modelCache);
+ createCacheHandles(mDataCache, dataCacheMode, &dataCache);
+ dataCacheMode[i] = AccessMode::READ_WRITE;
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel);
+ if (checkEarlyTermination(supported)) return;
+ ASSERT_NE(preparedModel, nullptr);
+ // Execute and verify results.
+ generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
+ get_examples(),
+ testModel.relaxComputationFloat32toFloat16,
+ /*testDynamicOutputShape=*/false);
+ // Check if prepareModelFromCache fails.
+ preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
}
}
TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) {
// Create test HIDL model and compile.
Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
+ std::vector<AccessMode> modelCacheMode(mNumModelCache, AccessMode::READ_WRITE);
+ std::vector<AccessMode> dataCacheMode(mNumDataCache, AccessMode::READ_WRITE);
// Save the compilation to cache.
{
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::NONE);
- }
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ saveModelToCache(testModel, modelCache, dataCache, &supported);
+ if (checkEarlyTermination(supported)) return;
}
- // cache1 with invalid access mode.
- {
- preparedModel = nullptr;
+ // Go through each handle in model cache, test with invalid access mode.
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ sp<IPreparedModel> preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ modelCacheMode[i] = AccessMode::WRITE_ONLY;
+ createCacheHandles(mModelCache, modelCacheMode, &modelCache);
+ createCacheHandles(mDataCache, dataCacheMode, &dataCache);
+ modelCacheMode[i] = AccessMode::READ_WRITE;
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
}
- // cache2 with invalid access mode.
- {
- preparedModel = nullptr;
+ // Go through each handle in data cache, test with invalid access mode.
+ for (uint32_t i = 0; i < mNumDataCache; i++) {
+ sp<IPreparedModel> preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ dataCacheMode[i] = AccessMode::WRITE_ONLY;
+ createCacheHandles(mModelCache, modelCacheMode, &modelCache);
+ createCacheHandles(mDataCache, dataCacheMode, &dataCache);
+ dataCacheMode[i] = AccessMode::READ_WRITE;
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
}
}
-TEST_F(CompilationCachingTest, SaveToCacheInvalidOffset) {
- // Create test HIDL model and compile.
- Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
-
- // cache1 with invalid file descriptor offset.
- {
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- uint8_t dummyByte = 0;
- // Advance offset by one byte.
- ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
-
- // cache2 with invalid file descriptor offset.
- {
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- uint8_t dummyByte = 0;
- // Advance offset by one byte.
- ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
-}
-
-TEST_F(CompilationCachingTest, SaveToCacheInvalidFileSize) {
- // Create test HIDL model and compile.
- Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
-
- // cache1 with invalid file size.
- {
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- uint8_t dummyByte = 0;
- // Write one byte and seek back to the beginning.
- ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1);
- ASSERT_EQ(lseek(cache1.getNativeHandle()->data[0], 0, SEEK_SET), 0);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
-
- // cache2 with invalid file size.
- {
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- uint8_t dummyByte = 0;
- // Write one byte and seek back to the beginning.
- ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1);
- ASSERT_EQ(lseek(cache2.getNativeHandle()->data[0], 0, SEEK_SET), 0);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
-}
-
class CompilationCachingSecurityTest : public CompilationCachingTest,
public ::testing::WithParamInterface<uint32_t> {
protected:
@@ -537,44 +888,44 @@
// Create test HIDL model and compile.
Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
- // Save the compilation to cache.
- {
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (checkEarlyTermination(status)) return;
- ASSERT_EQ(status, ErrorStatus::NONE);
- }
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ // Save the compilation to cache.
+ {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ saveModelToCache(testModel, modelCache, dataCache, &supported);
+ if (checkEarlyTermination(supported)) return;
+ }
- // Randomly flip one single bit of the cache entry.
- FILE* pFile = fopen(mCache1.c_str(), "r+");
- ASSERT_EQ(fseek(pFile, 0, SEEK_END), 0);
- long int fileSize = ftell(pFile);
- ASSERT_GT(fileSize, 0);
- ASSERT_EQ(fseek(pFile, getRandomInt(0l, fileSize - 1), SEEK_SET), 0);
- int readByte = fgetc(pFile);
- ASSERT_NE(readByte, EOF);
- ASSERT_EQ(fseek(pFile, -1, SEEK_CUR), 0);
- ASSERT_NE(fputc(static_cast<uint8_t>(readByte) ^ (1U << getRandomInt(0, 7)), pFile), EOF);
- fclose(pFile);
+ // Randomly flip one single bit of the cache entry.
+ FILE* pFile = fopen(mModelCache[i][0].c_str(), "r+");
+ ASSERT_EQ(fseek(pFile, 0, SEEK_END), 0);
+ long int fileSize = ftell(pFile);
+ if (fileSize == 0) {
+ fclose(pFile);
+ continue;
+ }
+ ASSERT_EQ(fseek(pFile, getRandomInt(0l, fileSize - 1), SEEK_SET), 0);
+ int readByte = fgetc(pFile);
+ ASSERT_NE(readByte, EOF);
+ ASSERT_EQ(fseek(pFile, -1, SEEK_CUR), 0);
+ ASSERT_NE(fputc(static_cast<uint8_t>(readByte) ^ (1U << getRandomInt(0, 7)), pFile), EOF);
+ fclose(pFile);
- // Retrieve preparedModel from cache, expect failure.
- {
- preparedModel = nullptr;
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- ASSERT_EQ(preparedModel, nullptr);
+ // Retrieve preparedModel from cache, expect failure.
+ {
+ sp<IPreparedModel> preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
}
}
@@ -583,40 +934,37 @@
// Create test HIDL model and compile.
Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
- // Save the compilation to cache.
- {
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (checkEarlyTermination(status)) return;
- ASSERT_EQ(status, ErrorStatus::NONE);
- }
+ for (uint32_t i = 0; i < mNumModelCache; i++) {
+ // Save the compilation to cache.
+ {
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ saveModelToCache(testModel, modelCache, dataCache, &supported);
+ if (checkEarlyTermination(supported)) return;
+ }
- // Randomly append bytes to the cache entry.
- FILE* pFile = fopen(mCache1.c_str(), "a");
- uint32_t appendLength = getRandomInt(1, 256);
- for (uint32_t i = 0; i < appendLength; i++) {
- ASSERT_NE(fputc(getRandomInt<uint8_t>(0, 255), pFile), EOF);
- }
- fclose(pFile);
+ // Randomly append bytes to the cache entry.
+ FILE* pFile = fopen(mModelCache[i][0].c_str(), "a");
+ uint32_t appendLength = getRandomInt(1, 256);
+ for (uint32_t i = 0; i < appendLength; i++) {
+ ASSERT_NE(fputc(getRandomInt<uint8_t>(0, 255), pFile), EOF);
+ }
+ fclose(pFile);
- // Retrieve preparedModel from cache, expect failure.
- {
- preparedModel = nullptr;
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- ASSERT_EQ(preparedModel, nullptr);
+ // Retrieve preparedModel from cache, expect failure.
+ {
+ sp<IPreparedModel> preparedModel = nullptr;
+ ErrorStatus status;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ ASSERT_EQ(preparedModel, nullptr);
+ }
}
}
@@ -625,20 +973,15 @@
// Create test HIDL model and compile.
Model testModel = createTestModel();
- sp<IPreparedModel> preparedModel = nullptr;
- generated_tests::PrepareModel(device, testModel, &preparedModel);
- // Terminate early if the driver cannot prepare the model.
- if (preparedModel == nullptr) return;
// Save the compilation to cache.
{
- ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
- saveModelToCache(preparedModel, cache1, cache2, &status);
- if (checkEarlyTermination(status)) return;
- ASSERT_EQ(status, ErrorStatus::NONE);
+ bool supported;
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ saveModelToCache(testModel, modelCache, dataCache, &supported);
+ if (checkEarlyTermination(supported)) return;
}
// Randomly flip one single bit in mToken.
@@ -647,12 +990,12 @@
// Retrieve the preparedModel from cache, expect failure.
{
- preparedModel = nullptr;
+ sp<IPreparedModel> preparedModel = nullptr;
ErrorStatus status;
- hidl_handle cache1, cache2;
- createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
- createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
- prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+ hidl_vec<hidl_handle> modelCache, dataCache;
+ createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
+ createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
}
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index 3b8e3dd..2988211 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -33,6 +33,7 @@
using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -54,7 +55,8 @@
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus =
- device->prepareModel_1_2(model, preference, preparedModelCallback);
+ device->prepareModel_1_2(model, preference, hidl_vec<hidl_handle>(),
+ hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
@@ -388,8 +390,9 @@
case OperationType::GROUPED_CONV_2D:
case OperationType::DEPTHWISE_CONV_2D:
case OperationType::CONV_2D: {
- if (operand == 1 && (type == OperandType::TENSOR_QUANT8_ASYMM ||
- type == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL)) {
+ if (operand == operation.inputs[1] &&
+ (type == OperandType::TENSOR_QUANT8_ASYMM ||
+ type == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL)) {
return true;
}
} break;
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index d411da4..b15f657 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -37,6 +37,7 @@
using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
using ::android::hidl::memory::V1_0::IMemory;
+using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
using test_helper::for_all;
using test_helper::MixedTyped;
using test_helper::MixedTypedExample;
@@ -66,7 +67,8 @@
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
- model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
+ model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec<hidl_handle>(),
+ hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
index da78f41..1d79ff6 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
@@ -26,6 +26,10 @@
sap->connectReq(token, maxMsgSize);
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(sapCb->sapResponseToken, token);
+
+ // Modem side need time for connect to finish. Adding a waiting time to prevent
+ // disconnect being requested right after connect request.
+ sleep(1);
}
/*
diff --git a/vibrator/1.3/Android.bp b/vibrator/1.3/Android.bp
index 28370d6..a2ff784 100644
--- a/vibrator/1.3/Android.bp
+++ b/vibrator/1.3/Android.bp
@@ -8,6 +8,7 @@
},
srcs: [
"IVibrator.hal",
+ "types.hal",
],
interfaces: [
"android.hardware.vibrator@1.0",
diff --git a/vibrator/1.3/IVibrator.hal b/vibrator/1.3/IVibrator.hal
index 01c2801..1c870ee 100644
--- a/vibrator/1.3/IVibrator.hal
+++ b/vibrator/1.3/IVibrator.hal
@@ -16,6 +16,7 @@
package android.hardware.vibrator@1.3;
+import @1.0::EffectStrength;
import @1.0::Status;
import @1.2::IVibrator;
@@ -41,4 +42,18 @@
* not supported by the device.
*/
setExternalControl(bool enabled) generates (Status status);
+
+ /**
+ * Fire off a predefined haptic event.
+ *
+ * @param event The type of haptic event to trigger.
+ * @return status Whether the effect was successfully performed or not. Must
+ * return Status::UNSUPPORTED_OPERATION if the effect is not supported.
+ * @return lengthMs The length of time the event is expected to take in
+ * milliseconds. This doesn't need to be perfectly accurate, but should be a reasonable
+ * approximation. Should be a positive, non-zero value if the returned status is Status::OK,
+ * and set to 0 otherwise.
+ */
+ perform_1_3(Effect effect, EffectStrength strength)
+ generates (Status status, uint32_t lengthMs);
};
diff --git a/vibrator/1.3/example/Vibrator.cpp b/vibrator/1.3/example/Vibrator.cpp
index bb9a057..eb50187 100644
--- a/vibrator/1.3/example/Vibrator.cpp
+++ b/vibrator/1.3/example/Vibrator.cpp
@@ -74,22 +74,9 @@
// Methods from ::android::hardware::vibrator::V1_2::IVibrator follow.
-Return<void> Vibrator::perform_1_2(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
- uint8_t amplitude;
- uint32_t ms;
- Status status;
-
- ALOGI("Perform: Effect %s\n", effectToName(effect));
-
- amplitude = strengthToAmplitude(strength);
- setAmplitude(amplitude);
-
- ms = effectToMs(effect);
- status = activate(ms);
-
- _hidl_cb(status, ms);
-
- return Void();
+Return<void> Vibrator::perform_1_2(V1_2::Effect effect, EffectStrength strength,
+ perform_cb _hidl_cb) {
+ return perform_1_3(static_cast<V1_3::Effect>(effect), strength, _hidl_cb);
}
// Methods from ::android::hardware::vibrator::V1_3::IVibrator follow.
@@ -110,6 +97,24 @@
}
}
+Return<void> Vibrator::perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
+ uint8_t amplitude;
+ uint32_t ms;
+ Status status;
+
+ ALOGI("Perform: Effect %s\n", effectToName(effect));
+
+ amplitude = strengthToAmplitude(strength);
+ setAmplitude(amplitude);
+
+ ms = effectToMs(effect);
+ status = activate(ms);
+
+ _hidl_cb(status, ms);
+
+ return Void();
+}
+
// Private methods follow.
Status Vibrator::enable(bool enabled) {
@@ -184,6 +189,7 @@
case Effect::DOUBLE_CLICK:
return 15;
case Effect::TICK:
+ case Effect::TEXTURE_TICK:
return 5;
case Effect::THUD:
return 5;
diff --git a/vibrator/1.3/example/Vibrator.h b/vibrator/1.3/example/Vibrator.h
index a931b63..8cf0b1e 100644
--- a/vibrator/1.3/example/Vibrator.h
+++ b/vibrator/1.3/example/Vibrator.h
@@ -27,7 +27,6 @@
using android::hardware::vibrator::V1_0::EffectStrength;
using android::hardware::vibrator::V1_0::Status;
-using android::hardware::vibrator::V1_2::Effect;
class Vibrator : public IVibrator {
public:
@@ -46,11 +45,13 @@
perform_cb _hidl_cb) override;
// Methods from ::android::hardware::vibrator::V1_2::IVibrator follow.
- Return<void> perform_1_2(Effect effect, EffectStrength strength, perform_cb _hidl_cb) override;
+ Return<void> perform_1_2(V1_2::Effect effect, EffectStrength strength,
+ perform_cb _hidl_cb) override;
// Methods from ::android::hardware::vibrator::V1_3::IVibrator follow.
Return<bool> supportsExternalControl() override;
Return<Status> setExternalControl(bool enabled) override;
+ Return<void> perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) override;
private:
Status enable(bool enabled);
diff --git a/vibrator/1.3/types.hal b/vibrator/1.3/types.hal
new file mode 100644
index 0000000..ceb62a5
--- /dev/null
+++ b/vibrator/1.3/types.hal
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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.vibrator@1.3;
+
+import @1.2::Effect;
+
+enum Effect : @1.2::Effect {
+ /**
+ * A soft tick effect meant to be played as a texture.
+ *
+ * A soft, short sensation like the tick of a clock. Unlike regular effects, texture effects
+ * are expected to be played multiple times in quick succession, replicating a specific
+ * texture to the user as a form of haptic feedback.
+ */
+ TEXTURE_TICK
+};
diff --git a/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
index a67d1dc..818f9c7 100644
--- a/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
+++ b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
@@ -24,9 +24,16 @@
#include <unistd.h>
using ::android::sp;
+using ::android::hardware::hidl_enum_range;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::vibrator::V1_0::EffectStrength;
using ::android::hardware::vibrator::V1_0::Status;
+using ::android::hardware::vibrator::V1_3::Effect;
using ::android::hardware::vibrator::V1_3::IVibrator;
+#define EXPECT_OK(ret) ASSERT_TRUE((ret).isOk())
+
// Test environment for Vibrator HIDL HAL.
class VibratorHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
public:
@@ -71,6 +78,74 @@
}
}
+static void validatePerformEffectUnsupportedOperation(Status status, uint32_t lengthMs) {
+ ASSERT_EQ(Status::UNSUPPORTED_OPERATION, status);
+ ASSERT_EQ(static_cast<uint32_t>(0), lengthMs)
+ << "Effects that return UNSUPPORTED_OPERATION must have a duration of zero";
+}
+
+static void validatePerformEffect(Status status, uint32_t lengthMs) {
+ ASSERT_TRUE(status == Status::OK || status == Status::UNSUPPORTED_OPERATION);
+ if (status == Status::OK) {
+ ASSERT_LT(static_cast<uint32_t>(0), lengthMs)
+ << "Effects that return OK must return a positive duration";
+ } else {
+ validatePerformEffectUnsupportedOperation(status, lengthMs);
+ }
+}
+
+/*
+ * Test to make sure effects within the valid range return are either supported and return OK with
+ * a valid duration, or are unsupported and return UNSUPPORTED_OPERATION with a duration of 0.
+ */
+TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3) {
+ for (const auto& effect : hidl_enum_range<Effect>()) {
+ for (const auto& strength : hidl_enum_range<EffectStrength>()) {
+ EXPECT_OK(vibrator->perform_1_3(effect, strength, validatePerformEffect));
+ }
+ }
+}
+
+/*
+ * Test to make sure effect values above the valid range are rejected.
+ */
+TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3_BadEffects_AboveValidRange) {
+ Effect effect = *std::prev(hidl_enum_range<Effect>().end());
+ Effect badEffect = static_cast<Effect>(static_cast<int32_t>(effect) + 1);
+ EXPECT_OK(vibrator->perform_1_3(badEffect, EffectStrength::LIGHT,
+ validatePerformEffectUnsupportedOperation));
+}
+
+/*
+ * Test to make sure effect values below the valid range are rejected.
+ */
+TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3_BadEffects_BelowValidRange) {
+ Effect effect = *hidl_enum_range<Effect>().begin();
+ Effect badEffect = static_cast<Effect>(static_cast<int32_t>(effect) - 1);
+ EXPECT_OK(vibrator->perform_1_3(badEffect, EffectStrength::LIGHT,
+ validatePerformEffectUnsupportedOperation));
+}
+
+/*
+ * Test to make sure strength values above the valid range are rejected.
+ */
+TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3_BadStrength_AboveValidRange) {
+ EffectStrength strength = *std::prev(hidl_enum_range<EffectStrength>().end());
+ EffectStrength badStrength = static_cast<EffectStrength>(static_cast<int32_t>(strength) + 1);
+ EXPECT_OK(vibrator->perform_1_3(Effect::THUD, badStrength,
+ validatePerformEffectUnsupportedOperation));
+}
+
+/*
+ * Test to make sure strength values below the valid range are rejected.
+ */
+TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3_BadStrength_BelowValidRange) {
+ EffectStrength strength = *hidl_enum_range<EffectStrength>().begin();
+ EffectStrength badStrength = static_cast<EffectStrength>(static_cast<int32_t>(strength) - 1);
+ EXPECT_OK(vibrator->perform_1_3(Effect::THUD, badStrength,
+ validatePerformEffectUnsupportedOperation));
+}
+
int main(int argc, char** argv) {
::testing::AddGlobalTestEnvironment(VibratorHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index 727aac5..3697d50 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -114,7 +114,7 @@
std::unique_ptr<DIR, decltype(&closedir)> dir_dump(
opendir(kTombstoneFolderPath), closedir);
if (!dir_dump) {
- LOG(ERROR) << "Failed to open directory: " << strerror(errno);
+ PLOG(ERROR) << "Failed to open directory";
return false;
}
struct dirent* dp;
@@ -128,8 +128,7 @@
struct stat cur_file_stat;
std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) {
- LOG(ERROR) << "Failed to get file stat for " << cur_file_path
- << ": " << strerror(errno);
+ PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
success = false;
continue;
}
@@ -144,7 +143,7 @@
if (cur_file_count > kMaxRingBufferFileNum ||
cur_file.first < delete_files_before) {
if (unlink(cur_file.second.c_str()) != 0) {
- LOG(ERROR) << "Error deleting file " << strerror(errno);
+ PLOG(ERROR) << "Error deleting file";
success = false;
}
cur_file_count--;
@@ -168,13 +167,11 @@
major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
if (write(out_fd, read_buf.data(), llen) == -1) {
- LOG(ERROR) << "Error writing cpio header to file " << file_name << " "
- << strerror(errno);
+ PLOG(ERROR) << "Error writing cpio header to file " << file_name;
return false;
}
if (write(out_fd, file_name, file_name_len) == -1) {
- LOG(ERROR) << "Error writing filename to file " << file_name << " "
- << strerror(errno);
+ PLOG(ERROR) << "Error writing filename to file " << file_name;
return false;
}
@@ -183,8 +180,7 @@
if (llen != 0) {
const uint32_t zero = 0;
if (write(out_fd, &zero, 4 - llen) == -1) {
- LOG(ERROR) << "Error padding 0s to file " << file_name << " "
- << strerror(errno);
+ PLOG(ERROR) << "Error padding 0s to file " << file_name;
return false;
}
}
@@ -200,17 +196,17 @@
while (llen > 0) {
ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
if (bytes_read == -1) {
- LOG(ERROR) << "Error reading file " << strerror(errno);
+ PLOG(ERROR) << "Error reading file";
return ++n_error;
}
llen -= bytes_read;
if (write(out_fd, read_buf.data(), bytes_read) == -1) {
- LOG(ERROR) << "Error writing data to file " << strerror(errno);
+ PLOG(ERROR) << "Error writing data to file";
return ++n_error;
}
if (bytes_read == 0) { // this should never happen, but just in case
// to unstuck from while loop
- LOG(ERROR) << "Unexpected read result for " << strerror(errno);
+ PLOG(ERROR) << "Unexpected read result";
n_error++;
break;
}
@@ -219,7 +215,7 @@
if (llen != 0) {
const uint32_t zero = 0;
if (write(out_fd, &zero, 4 - llen) == -1) {
- LOG(ERROR) << "Error padding 0s to file " << strerror(errno);
+ PLOG(ERROR) << "Error padding 0s to file";
return ++n_error;
}
}
@@ -234,7 +230,7 @@
sprintf(read_buf.data(), "070701%040X%056X%08XTRAILER!!!", 1,
0x0b, 0) +
4) == -1) {
- LOG(ERROR) << "Error writing trailing bytes " << strerror(errno);
+ PLOG(ERROR) << "Error writing trailing bytes";
return false;
}
return true;
@@ -249,7 +245,7 @@
std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir),
closedir);
if (!dir_dump) {
- LOG(ERROR) << "Failed to open directory: " << strerror(errno);
+ PLOG(ERROR) << "Failed to open directory";
return ++n_error;
}
while ((dp = readdir(dir_dump.get()))) {
@@ -263,15 +259,13 @@
struct stat st;
const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
if (stat(cur_file_path.c_str(), &st) == -1) {
- LOG(ERROR) << "Failed to get file stat for " << cur_file_path
- << ": " << strerror(errno);
+ PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
n_error++;
continue;
}
const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
if (fd_read == -1) {
- LOG(ERROR) << "Failed to open file " << cur_file_path << " "
- << strerror(errno);
+ PLOG(ERROR) << "Failed to open file " << cur_file_path;
n_error++;
continue;
}
@@ -1158,6 +1152,16 @@
// This probably is not a critical failure?
LOG(ERROR) << "Failed to register radio mode change callback";
}
+ // Extract and save the version information into property.
+ std::pair<WifiStatus, IWifiChip::ChipDebugInfo> version_info;
+ version_info = WifiChip::requestChipDebugInfoInternal();
+ if (WifiStatusCode::SUCCESS == version_info.first.code) {
+ property_set("vendor.wlan.firmware.version",
+ version_info.second.firmwareDescription.c_str());
+ property_set("vendor.wlan.driver.version",
+ version_info.second.driverDescription.c_str());
+ }
+
return createWifiStatus(WifiStatusCode::SUCCESS);
}
@@ -1373,14 +1377,14 @@
kTombstoneFolderPath + item.first + "XXXXXXXXXX";
const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
if (dump_fd == -1) {
- LOG(ERROR) << "create file failed: " << strerror(errno);
+ PLOG(ERROR) << "create file failed";
return false;
}
unique_fd file_auto_closer(dump_fd);
for (const auto& cur_block : cur_buffer.getData()) {
if (write(dump_fd, cur_block.data(),
sizeof(cur_block[0]) * cur_block.size()) == -1) {
- LOG(ERROR) << "Error writing to file " << strerror(errno);
+ PLOG(ERROR) << "Error writing to file";
}
}
}