Merge "Camera: Document bufferSize for JPEG_APP_SEGMENTS stream"
diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal
index ffe4506..8f8a888 100644
--- a/audio/common/5.0/types.hal
+++ b/audio/common/5.0/types.hal
@@ -643,8 +643,10 @@
int32_t device;
} alsa; // used for USB_*
} address;
- string busAddress; // used for BUS
- string rSubmixAddress; // used for REMOTE_SUBMIX
+ /** Arbitrary BUS device unique address. Should not be interpreted by the framework. */
+ string busAddress;
+ /** Arbitrary REMOTE_SUBMIX device unique address. Should not be interpreted by the HAL. */
+ string rSubmixAddress;
};
/**
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index a22cc1c..7f8b6a0 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -142,14 +142,13 @@
android::DeviceVector availableOutputDevices;
android::DeviceVector availableInputDevices;
sp<android::DeviceDescriptor> defaultOutputDevice;
- android::VolumeCurvesCollection volumes;
};
class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig {
public:
PolicyConfig()
: AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
- defaultOutputDevice, &volumes) {
+ defaultOutputDevice) {
for (const char* location : kConfigLocations) {
std::string path = std::string(location) + '/' + kConfigFileName;
if (access(path.c_str(), F_OK) == 0) {
diff --git a/audio/effect/all-versions/default/AcousticEchoCancelerEffect.cpp b/audio/effect/all-versions/default/AcousticEchoCancelerEffect.cpp
index 0b60622..137ea24 100644
--- a/audio/effect/all-versions/default/AcousticEchoCancelerEffect.cpp
+++ b/audio/effect/all-versions/default/AcousticEchoCancelerEffect.cpp
@@ -165,6 +165,11 @@
return mEffect->close();
}
+Return<void> AcousticEchoCancelerEffect::debug(const hidl_handle& fd,
+ const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IAcousticEchoCancelerEffect
// follow.
Return<Result> AcousticEchoCancelerEffect::setEchoDelay(uint32_t echoDelayMs) {
diff --git a/audio/effect/all-versions/default/AcousticEchoCancelerEffect.h b/audio/effect/all-versions/default/AcousticEchoCancelerEffect.h
index c18f88b..971f64d 100644
--- a/audio/effect/all-versions/default/AcousticEchoCancelerEffect.h
+++ b/audio/effect/all-versions/default/AcousticEchoCancelerEffect.h
@@ -88,6 +88,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from
// ::android::hardware::audio::effect::CPP_VERSION::IAcousticEchoCancelerEffect follow.
diff --git a/audio/effect/all-versions/default/AutomaticGainControlEffect.cpp b/audio/effect/all-versions/default/AutomaticGainControlEffect.cpp
index 651dd1b..655a4cd 100644
--- a/audio/effect/all-versions/default/AutomaticGainControlEffect.cpp
+++ b/audio/effect/all-versions/default/AutomaticGainControlEffect.cpp
@@ -178,6 +178,11 @@
return mEffect->close();
}
+Return<void> AutomaticGainControlEffect::debug(const hidl_handle& fd,
+ const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IAutomaticGainControlEffect
// follow.
Return<Result> AutomaticGainControlEffect::setTargetLevel(int16_t targetLevelMb) {
diff --git a/audio/effect/all-versions/default/AutomaticGainControlEffect.h b/audio/effect/all-versions/default/AutomaticGainControlEffect.h
index a281b1d..67e260a 100644
--- a/audio/effect/all-versions/default/AutomaticGainControlEffect.h
+++ b/audio/effect/all-versions/default/AutomaticGainControlEffect.h
@@ -90,6 +90,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from
// ::android::hardware::audio::effect::CPP_VERSION::IAutomaticGainControlEffect follow.
diff --git a/audio/effect/all-versions/default/BassBoostEffect.cpp b/audio/effect/all-versions/default/BassBoostEffect.cpp
index 6f7763d..04fd486 100644
--- a/audio/effect/all-versions/default/BassBoostEffect.cpp
+++ b/audio/effect/all-versions/default/BassBoostEffect.cpp
@@ -161,6 +161,10 @@
return mEffect->close();
}
+Return<void> BassBoostEffect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IBassBoostEffect follow.
Return<void> BassBoostEffect::isStrengthSupported(isStrengthSupported_cb _hidl_cb) {
return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH_SUPPORTED, _hidl_cb);
diff --git a/audio/effect/all-versions/default/BassBoostEffect.h b/audio/effect/all-versions/default/BassBoostEffect.h
index a184ac2..b89bb22 100644
--- a/audio/effect/all-versions/default/BassBoostEffect.h
+++ b/audio/effect/all-versions/default/BassBoostEffect.h
@@ -90,6 +90,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IBassBoostEffect follow.
Return<void> isStrengthSupported(isStrengthSupported_cb _hidl_cb) override;
diff --git a/audio/effect/all-versions/default/DownmixEffect.cpp b/audio/effect/all-versions/default/DownmixEffect.cpp
index 94da70e..c001a5f 100644
--- a/audio/effect/all-versions/default/DownmixEffect.cpp
+++ b/audio/effect/all-versions/default/DownmixEffect.cpp
@@ -161,6 +161,10 @@
return mEffect->close();
}
+Return<void> DownmixEffect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IDownmixEffect follow.
Return<Result> DownmixEffect::setType(IDownmixEffect::Type preset) {
return mEffect->setParam(DOWNMIX_PARAM_TYPE, static_cast<downmix_type_t>(preset));
diff --git a/audio/effect/all-versions/default/DownmixEffect.h b/audio/effect/all-versions/default/DownmixEffect.h
index 6d34c28..40e462e 100644
--- a/audio/effect/all-versions/default/DownmixEffect.h
+++ b/audio/effect/all-versions/default/DownmixEffect.h
@@ -88,6 +88,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IDownmixEffect follow.
Return<Result> setType(IDownmixEffect::Type preset) override;
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 84608b6..3c0d878 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -710,6 +710,14 @@
return Result::OK;
}
+Return<void> Effect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
+ if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
+ uint32_t cmdData = fd->data[0];
+ (void)sendCommand(EFFECT_CMD_DUMP, "DUMP", sizeof(cmdData), &cmdData);
+ }
+ return Void();
+}
+
} // namespace implementation
} // namespace CPP_VERSION
} // namespace effect
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 1a2b039..3d99a0e 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -101,6 +101,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Utility methods for extending interfaces.
template <typename T>
diff --git a/audio/effect/all-versions/default/EnvironmentalReverbEffect.cpp b/audio/effect/all-versions/default/EnvironmentalReverbEffect.cpp
index 1ade7b8..78122d4 100644
--- a/audio/effect/all-versions/default/EnvironmentalReverbEffect.cpp
+++ b/audio/effect/all-versions/default/EnvironmentalReverbEffect.cpp
@@ -193,6 +193,11 @@
return mEffect->close();
}
+Return<void> EnvironmentalReverbEffect::debug(const hidl_handle& fd,
+ const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IEnvironmentalReverbEffect
// follow.
Return<Result> EnvironmentalReverbEffect::setBypass(bool bypass) {
diff --git a/audio/effect/all-versions/default/EnvironmentalReverbEffect.h b/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
index d06c3fc..bb422d4 100644
--- a/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
+++ b/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
@@ -92,6 +92,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from
// ::android::hardware::audio::effect::CPP_VERSION::IEnvironmentalReverbEffect follow.
diff --git a/audio/effect/all-versions/default/EqualizerEffect.cpp b/audio/effect/all-versions/default/EqualizerEffect.cpp
index f6177b7..1b983ec 100644
--- a/audio/effect/all-versions/default/EqualizerEffect.cpp
+++ b/audio/effect/all-versions/default/EqualizerEffect.cpp
@@ -184,6 +184,10 @@
return mEffect->close();
}
+Return<void> EqualizerEffect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IEqualizerEffect follow.
Return<void> EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) {
return mEffect->getIntegerParam(EQ_PARAM_NUM_BANDS, _hidl_cb);
diff --git a/audio/effect/all-versions/default/EqualizerEffect.h b/audio/effect/all-versions/default/EqualizerEffect.h
index 318c0db..b1cbefd 100644
--- a/audio/effect/all-versions/default/EqualizerEffect.h
+++ b/audio/effect/all-versions/default/EqualizerEffect.h
@@ -92,6 +92,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IEqualizerEffect follow.
Return<void> getNumBands(getNumBands_cb _hidl_cb) override;
diff --git a/audio/effect/all-versions/default/LoudnessEnhancerEffect.cpp b/audio/effect/all-versions/default/LoudnessEnhancerEffect.cpp
index 6918bdf..ebd5197 100644
--- a/audio/effect/all-versions/default/LoudnessEnhancerEffect.cpp
+++ b/audio/effect/all-versions/default/LoudnessEnhancerEffect.cpp
@@ -164,6 +164,11 @@
return mEffect->close();
}
+Return<void> LoudnessEnhancerEffect::debug(const hidl_handle& fd,
+ const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::ILoudnessEnhancerEffect
// follow.
Return<Result> LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) {
diff --git a/audio/effect/all-versions/default/LoudnessEnhancerEffect.h b/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
index 06c521c..8baf128 100644
--- a/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
+++ b/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
@@ -88,6 +88,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::effect::CPP_VERSION::ILoudnessEnhancerEffect
// follow.
diff --git a/audio/effect/all-versions/default/NoiseSuppressionEffect.cpp b/audio/effect/all-versions/default/NoiseSuppressionEffect.cpp
index 4756719..d01bbe5 100644
--- a/audio/effect/all-versions/default/NoiseSuppressionEffect.cpp
+++ b/audio/effect/all-versions/default/NoiseSuppressionEffect.cpp
@@ -173,6 +173,11 @@
return mEffect->close();
}
+Return<void> NoiseSuppressionEffect::debug(const hidl_handle& fd,
+ const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::INoiseSuppressionEffect
// follow.
Return<Result> NoiseSuppressionEffect::setSuppressionLevel(INoiseSuppressionEffect::Level level) {
diff --git a/audio/effect/all-versions/default/NoiseSuppressionEffect.h b/audio/effect/all-versions/default/NoiseSuppressionEffect.h
index f31ba3b..c49bf7b 100644
--- a/audio/effect/all-versions/default/NoiseSuppressionEffect.h
+++ b/audio/effect/all-versions/default/NoiseSuppressionEffect.h
@@ -90,6 +90,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::effect::CPP_VERSION::INoiseSuppressionEffect
// follow.
diff --git a/audio/effect/all-versions/default/PresetReverbEffect.cpp b/audio/effect/all-versions/default/PresetReverbEffect.cpp
index 97723f5..4a2a3a4 100644
--- a/audio/effect/all-versions/default/PresetReverbEffect.cpp
+++ b/audio/effect/all-versions/default/PresetReverbEffect.cpp
@@ -161,6 +161,11 @@
return mEffect->close();
}
+Return<void> PresetReverbEffect::debug(const hidl_handle& fd,
+ const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IPresetReverbEffect follow.
Return<Result> PresetReverbEffect::setPreset(IPresetReverbEffect::Preset preset) {
return mEffect->setParam(REVERB_PARAM_PRESET, static_cast<t_reverb_presets>(preset));
diff --git a/audio/effect/all-versions/default/PresetReverbEffect.h b/audio/effect/all-versions/default/PresetReverbEffect.h
index 8971976..58a6829 100644
--- a/audio/effect/all-versions/default/PresetReverbEffect.h
+++ b/audio/effect/all-versions/default/PresetReverbEffect.h
@@ -88,6 +88,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IPresetReverbEffect
// follow.
diff --git a/audio/effect/all-versions/default/VirtualizerEffect.cpp b/audio/effect/all-versions/default/VirtualizerEffect.cpp
index 4d597c7..1b69a90 100644
--- a/audio/effect/all-versions/default/VirtualizerEffect.cpp
+++ b/audio/effect/all-versions/default/VirtualizerEffect.cpp
@@ -173,6 +173,10 @@
return mEffect->close();
}
+Return<void> VirtualizerEffect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IVirtualizerEffect follow.
Return<bool> VirtualizerEffect::isStrengthSupported() {
bool halSupported = false;
diff --git a/audio/effect/all-versions/default/VirtualizerEffect.h b/audio/effect/all-versions/default/VirtualizerEffect.h
index e7302f9..c630b2e 100644
--- a/audio/effect/all-versions/default/VirtualizerEffect.h
+++ b/audio/effect/all-versions/default/VirtualizerEffect.h
@@ -89,6 +89,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IVirtualizerEffect
// follow.
diff --git a/audio/effect/all-versions/default/VisualizerEffect.cpp b/audio/effect/all-versions/default/VisualizerEffect.cpp
index 77bf46b..ae533bf 100644
--- a/audio/effect/all-versions/default/VisualizerEffect.cpp
+++ b/audio/effect/all-versions/default/VisualizerEffect.cpp
@@ -162,6 +162,10 @@
return mEffect->close();
}
+Return<void> VisualizerEffect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+ return mEffect->debug(fd, options);
+}
+
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IVisualizerEffect follow.
Return<Result> VisualizerEffect::setCaptureSize(uint16_t captureSize) {
Result retval = mEffect->setParam(VISUALIZER_PARAM_CAPTURE_SIZE, captureSize);
diff --git a/audio/effect/all-versions/default/VisualizerEffect.h b/audio/effect/all-versions/default/VisualizerEffect.h
index 42c77a2..315f844 100644
--- a/audio/effect/all-versions/default/VisualizerEffect.h
+++ b/audio/effect/all-versions/default/VisualizerEffect.h
@@ -88,6 +88,7 @@
Return<Result> setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) override;
Return<Result> close() override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::effect::CPP_VERSION::IVisualizerEffect follow.
Return<Result> setCaptureSize(uint16_t captureSize) override;
diff --git a/automotive/evs/OWNERS b/automotive/evs/OWNERS
new file mode 100644
index 0000000..fec2a3a
--- /dev/null
+++ b/automotive/evs/OWNERS
@@ -0,0 +1,3 @@
+changyeon@google.com
+haoxiangl@google.com
+swan@google.com
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index e874146..3efaaec 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -282,7 +282,6 @@
| VehiclePropertyType:INT32
| VehicleArea:SEAT),
-
/**
* Current odometer value of the vehicle
*
@@ -1112,6 +1111,91 @@
| VehiclePropertyType:INT32
| VehicleArea:SEAT),
+ /**
+ * Distance units for display
+ *
+ * Indicates which units the car is using to display distances to the user. Eg. Mile, Meter
+ * Kilometer.
+ *
+ * Distance units are defined in VehicleUnit.
+ * VehiclePropConfig.configArray is used to indicate the supported distance display units.
+ * For example: configArray[0] = 0x21 // METER
+ * configArray[1] = 0x23 // KILOMETER
+ * configArray[2] = 0x24 // MILE
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ DISTANCE_DISPLAY_UNITS = (
+ 0x0600
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:GLOBAL),
+
+ /**
+ * Fuel volume units for display
+ *
+ * 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
+ * configArray[1] = 0x42 // GALLON
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ FUEL_VOLUME_DISPLAY_UNITS = (
+ 0x0601
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:GLOBAL),
+
+ /**
+ * Tire pressure units for display
+ *
+ * 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
+ * configArray[1] = 0x71 // PSI
+ * configArray[2] = 0x72 // BAR
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ TIRE_PRESSURE_DISPLAY_UNITS = (
+ 0x0602
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:GLOBAL),
+
+ /**
+ * EV battery units for display
+ *
+ * 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
+ * configArray[1] = 0x64 // ampere-hours
+ * configArray[2] = 0x65 // kilowatt-hours
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ EV_BATTERY_DISPLAY_UNITS = (
+ 0x0603
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:GLOBAL),
/**
* Outside temperature
@@ -1779,6 +1863,22 @@
| VehicleArea:SEAT),
/**
+ * Seat Occupancy
+ *
+ * Indicates whether a particular seat is occupied or not, to the best of the car's ability
+ * to determine. Valid values are from the VehicleSeatOccupancyState enum.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleSeatOccupancyState
+ */
+ SEAT_OCCUPANCY = (
+ 0x0BB0
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:SEAT),
+
+ /**
* Window Position
*
* Min = window up / closed
@@ -2113,6 +2213,83 @@
| VehiclePropertyGroup:SYSTEM
| VehiclePropertyType:INT32
| VehicleArea:GLOBAL),
+
+ /**
+ * Cabin lights
+ *
+ * Return current status of cabin lights.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleLightState
+ */
+ CABIN_LIGHTS_STATE = (
+ 0x0F01
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:GLOBAL),
+
+ /**
+ * Cabin lights switch
+ *
+ * The position of the physical switch which controls the cabin lights.
+ * This might be different than the CABIN_LIGHTS_STATE if the lights are on because a door
+ * is open or because of a voice command.
+ * For example, while the switch is in the "off" or "automatic" position.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ CABIN_LIGHTS_SWITCH = (
+ 0x0F02
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:GLOBAL),
+
+ /**
+ * Reading lights
+ *
+ * Return current status of reading lights.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleLightState
+ */
+ READING_LIGHTS_STATE = (
+ 0x0F03
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:SEAT),
+
+ /**
+ * Reading lights switch
+ *
+ * The position of the physical switch which controls the reading lights.
+ * This might be different than the READING_LIGHTS_STATE if the lights are on because a door
+ * is open or because of a voice command.
+ * For example, while the switch is in the "off" or "automatic" position.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ READING_LIGHTS_SWITCH = (
+ 0x0F04
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:SEAT),
+
+};
+
+/**
+ * Used by seat occupancy to enumerate the current occupancy state of the seat.
+ */
+enum VehicleSeatOccupancyState : int32_t {
+
+ UNKNOWN = 0,
+ VACANT = 1,
+ OCCUPIED = 2
};
/**
@@ -2404,10 +2581,13 @@
MILLIMETER = 0x20,
METER = 0x21,
KILOMETER = 0x23,
+ MILE = 0x24,
CELSIUS = 0x30,
FAHRENHEIT = 0x31,
KELVIN = 0x32,
MILLILITER = 0x40,
+ LITER = 0x41,
+ GALLON = 0x42,
NANO_SECS = 0x50,
SECS = 0x53,
YEAR = 0x59,
@@ -2417,8 +2597,12 @@
MILLIAMPERE = 0x61,
MILLIVOLT = 0x62,
MILLIWATTS = 0x63,
+ AMPERE_HOURS = 0x64,
+ KILOWATT_HOUR = 0x65,
KILOPASCAL = 0x70,
+ PSI = 0x71,
+ BAR = 0x72,
DEGREES = 0x80,
};
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 2f9fb6e..244d7a0 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -121,7 +121,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.cas</name>
- <version>1.0-1</version>
+ <version>1.1</version>
<interface>
<name>IMediaCasService</name>
<instance>default</instance>
diff --git a/current.txt b/current.txt
index b47bc34..79aafd7 100644
--- a/current.txt
+++ b/current.txt
@@ -418,7 +418,7 @@
9471b12b1c255bb530695720bc4174bd74987b75b1f820854af8944bc8c215c9 android.hardware.audio@5.0::IStreamOut
1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback
83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types
-edda213e520f387a3e367834b0772978b308a0f59b54479990aa9411aee9bcc4 android.hardware.audio.common@5.0::types
+894af04bebfe7da5b6791eefeb6eb3627da63d5efea735f16876d11d8ca4f61d 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
@@ -464,12 +464,12 @@
7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss
2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback
1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil
-52e56490d35b4214d68c44f013e22bdf681fd6f8e5947c643dbb8453f9a03dcd android.hardware.gnss@2.0::IGnss
-0676e99eda39ff32f6891bcb56ea27df17007c439b9f900aa9a3919776920c23 android.hardware.gnss@2.0::IGnssCallback
+6e2f9a44375a0ae0b49ca7d711cb88945189d398535078408269e1e85889061d android.hardware.gnss@2.0::IGnss
+d815623a6d1ba4abf21248b84eca70a2bfab03058a88b68a29c063ce8aee6b5c android.hardware.gnss@2.0::IGnssCallback
ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration
c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement
-08615296d42451856f82c4953b45c4257d0a7b935fd98557c2ee2812c79fe0c3 android.hardware.gnss@2.0::IGnssMeasurementCallback
-141269652bcf30a7557edc4cd4311aa3e2ac67a252a7e8d3959b956d35793344 android.hardware.gnss@2.0::types
+089338944c45f66f25ba4ee958c161c42fefeb73ec60e4451f3535a1b3fd10c7 android.hardware.gnss@2.0::IGnssMeasurementCallback
+9e66234e65bcde75733d75d8b5d5cc094c2a5e14b074a25cd3f9ad141dc56f60 android.hardware.gnss@2.0::types
50623a69a88b1c8a05738e4af7d5f78e905f415ccb0e84c99d0a71ea182e9393 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections
6ef12cd95df73f8f80c25eb035d98ca4594f9cee571fdabea838a0b6016dd908 android.hardware.gnss.measurement_corrections@1.0::types
0d278956d7fc6fdf9ca9c42962ff2d73967bbb1c9f0b3e0b58d71b7095c286bc android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl
@@ -487,7 +487,7 @@
dd1ec219f5d2e2b33c6c0bcb92e63bbedb36f7c716413462848f6b6ae74fc864 android.hardware.health.storage@1.0::IStorage
2b4a14661e6a38617b7dd0c6ebb66a56a90e564674ac7697a14cb8a0cab92b2f android.hardware.health.storage@1.0::types
30006fde4cb1f255f2530208728bff692100411b20af5b66fa31a9196d51f00b android.hardware.input.classifier@1.0::IInputClassifier
-97d8757bb05eb23d6a218bda374e095dfbb064c47714e2f859963c11f433e822 android.hardware.input.common@1.0::types
+0300c7667030da36c3de585f176ce18ff4b0d2615446d4930f331097378c06ef android.hardware.input.common@1.0::types
24ae089981d58bc4cc74d75a6055bf357338ae6744ce1b467c5b4a9c470aba6d android.hardware.media.bufferpool@2.0::IAccessor
897f45ee7db24ef227dea83ca3e4de72d53ff6bb7adc7983c90a650a1a6ff576 android.hardware.media.bufferpool@2.0::IClientManager
aee53b2865b4f7939fb3df6fae758d9750c14f93dd454b479fc74aa7978fda4f android.hardware.media.bufferpool@2.0::IConnection
@@ -512,12 +512,12 @@
cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc
abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types
4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats
-69c394e7fe3236beb6231a709865e8a882aac7a612c8dddf64f5a66028fa2c68 android.hardware.power.stats@1.0::types
-11620ce020b6ef8f5b63eb2a39390de4a2fbbccc0a5e558b5b1a0e22e33f63cf android.hardware.radio@1.3::IRadio
+2043037d5baaff604805757d06979aa861013a1e87430db745265339a8681f79 android.hardware.power.stats@1.0::types
+d5545a4090e5cf8b7f844121377d580926cb9137d693d8c66772ef99ca23e514 android.hardware.radio@1.3::IRadio
e9d0f11a52715f5a29d89e2d8e2e21db1e16a43174af6b9d51a62d705cda1455 android.hardware.radio@1.3::IRadioIndication
d233f0da44f55fdef0a95db5229231412787bb67695cd1ea197ce89a3c2908b9 android.hardware.radio@1.3::IRadioResponse
750a363c8cec70baa1aac19e275c15233c5898e93c6bb5155fa2ca7f365490dc android.hardware.radio@1.3::types
-21e6ce53f1759f6a213ca05bac3c0325ed911f74764d1c1f6fa5ed8068ade65b android.hardware.radio@1.4::IRadio
+4ac73ec1e4cfa535209e5e22547f08beb20ef812b4a29d0824780f52cbe2324d android.hardware.radio@1.4::IRadio
33d9e6895cca98aa56296bb01720d18b8acd0e4de4960beb712e63ad147438a5 android.hardware.radio@1.4::IRadioIndication
0cc0dd87c634aad36d7df22b2832839ef7ded71909dbcde11cfdd69dc0dc52b8 android.hardware.radio@1.4::IRadioResponse
29d34232cc3974626b08759e039fe788bded7695cdeb098458e3e11e4c7d3603 android.hardware.radio@1.4::types
@@ -534,7 +534,7 @@
ae5faa38538a9f50eb71eb7f9b998271124d2c64b761cb11c4d820c7732b4ddc android.hardware.sensors@2.0::ISensorsCallback
3a98242a57d0820dacaca0f7db52bec433eae1f21c498763c6f1ece611c3967b android.hardware.sensors@2.0::types
ce4b98211959449361146d4b1e5554dc841ceb4d4577154d7b2fb6d1eb504f76 android.hardware.soundtrigger@2.2::ISoundTriggerHw
-5cc81d517c5f3fef12e719b0f5683c7c99e3e8895fcb80e6f6653b454f463320 android.hardware.thermal@2.0::IThermal
+bd88b48639cae30982021024e22371076c76faa8466e38ca598529452b618eae android.hardware.thermal@2.0::IThermal
cc4d2ef36da776c475ad054f0f3416d8a8865def9d9e2129f10074b28e36d203 android.hardware.thermal@2.0::IThermalChangedCallback
b47f90302595874dfddb19bd05a054727bf18b3a930bc810ea14957b859ae8bf android.hardware.thermal@2.0::types
61bc302e7c974c59b25898c585c6e9685e8a81021b1bed3eedf5224198f2785a android.hardware.usb@1.2::IUsb
diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp
index 9b04be0..230dd90 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -25,6 +25,9 @@
"android.hidl.base@1.0",
],
types: [
+ "ElapsedRealtime",
+ "ElapsedRealtimeFlags",
+ "GnssLocation",
],
gen_java: true,
gen_java_constants: true,
diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal
index 1f1858e..2c149b7 100644
--- a/gnss/2.0/IGnss.hal
+++ b/gnss/2.0/IGnss.hal
@@ -20,6 +20,7 @@
import android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl;
import @1.1::IGnss;
+import GnssLocation;
import IGnssCallback;
import IGnssConfiguration;
import IGnssMeasurement;
@@ -94,4 +95,16 @@
* @return visibilityControlIface Handle to the IGnssVisibilityControl interface.
*/
getExtensionVisibilityControl() generates (IGnssVisibilityControl visibilityControlIface);
+
+ /**
+ * Injects current location from the best available location provider.
+ *
+ * Unlike injectLocation, this method may inject a recent GNSS location from the HAL
+ * implementation, if that is the best available location known to the framework.
+ *
+ * @param location Location information from the best available location provider.
+ *
+ * @return success Returns true if successful.
+ */
+ injectBestLocation_2_0(GnssLocation location) generates (bool success);
};
\ No newline at end of file
diff --git a/gnss/2.0/IGnssCallback.hal b/gnss/2.0/IGnssCallback.hal
index 6baff91..7924b64 100644
--- a/gnss/2.0/IGnssCallback.hal
+++ b/gnss/2.0/IGnssCallback.hal
@@ -18,6 +18,7 @@
import @1.0::IGnssCallback;
import @1.1::IGnssCallback;
+import GnssLocation;
/**
* The interface is required for the HAL to communicate certain information
@@ -44,4 +45,34 @@
*/
gnssSetCapabilitiesCb_2_0(bitfield<Capabilities> capabilities);
+ /**
+ * Called when a GNSS location is available.
+ *
+ * @param location Location information from HAL.
+ */
+ gnssLocationCb_2_0(GnssLocation location);
+
+ /**
+ * Callback for requesting Location.
+ *
+ * HAL implementation must call this when it wants the framework to provide locations to assist
+ * with GNSS HAL operation, for example, to assist with time to first fix, error recovery, or to
+ * supplement GNSS location for other clients of the GNSS HAL.
+ *
+ * If a request is made with independentFromGnss set to true, the framework must avoid
+ * providing locations derived from GNSS locations (such as "fused" location), to help improve
+ * information independence for situations such as error recovery.
+ *
+ * In response to this method call, GNSS HAL can expect zero, one, or more calls to
+ * IGnss::injectLocation or IGnss::injectBestLocation, dependent on availability of location
+ * from other sources, which may happen at some arbitrary delay. Generally speaking, HAL
+ * implementations must be able to handle calls to IGnss::injectLocation or
+ * IGnss::injectBestLocation at any time.
+ *
+ * @param independentFromGnss True if requesting a location that is independent from GNSS.
+ * @param isUserEmergency True if the location request is for delivery of this location to an
+ * emergency services endpoint, during a user-initiated emergency session (e.g.
+ * 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
diff --git a/gnss/2.0/IGnssMeasurementCallback.hal b/gnss/2.0/IGnssMeasurementCallback.hal
index fc44465..d5dc038 100644
--- a/gnss/2.0/IGnssMeasurementCallback.hal
+++ b/gnss/2.0/IGnssMeasurementCallback.hal
@@ -18,6 +18,7 @@
import @1.0::IGnssMeasurementCallback;
import @1.1::IGnssMeasurementCallback;
+import ElapsedRealtime;
/** The callback interface to report measurements from the HAL. */
interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback {
@@ -492,6 +493,12 @@
/** The GNSS clock time reading. */
GnssClock clock;
+
+ /**
+ * Timing information of the GNSS data synchronized with SystemClock.elapsedRealtimeNanos()
+ * clock.
+ */
+ ElapsedRealtime elapsedRealtime;
};
/**
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index 1efc9f5..599681b 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -17,7 +17,10 @@
#define LOG_TAG "Gnss"
#include "Gnss.h"
+
#include <log/log.h>
+#include <utils/SystemClock.h>
+
#include "AGnss.h"
#include "AGnssRil.h"
#include "GnssConfiguration.h"
@@ -40,6 +43,24 @@
sp<V2_0::IGnssCallback> Gnss::sGnssCallback_2_0 = nullptr;
sp<V1_1::IGnssCallback> Gnss::sGnssCallback_1_1 = nullptr;
+namespace {
+
+V2_0::GnssLocation getMockLocationV2_0() {
+ const ElapsedRealtime timestamp = {
+ .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+ .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
+ // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+ // In an actual implementation provide an estimate of the synchronization uncertainty
+ // or don't set the field.
+ .timeUncertaintyNs = 1000000};
+
+ V2_0::GnssLocation location = {.v1_0 = Utils::getMockLocation(), .elapsedRealtime = timestamp};
+ return location;
+}
+
+} // namespace
+
Gnss::Gnss() : mMinIntervalMs(1000) {}
Gnss::~Gnss() {
@@ -48,7 +69,7 @@
// Methods from V1_0::IGnss follow.
Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>&) {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return bool{};
}
@@ -61,7 +82,7 @@
mIsActive = true;
mThread = std::thread([this]() {
while (mIsActive == true) {
- const auto location = Utils::getMockLocation();
+ const auto location = getMockLocationV2_0();
this->reportLocation(location);
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
@@ -79,44 +100,44 @@
}
Return<void> Gnss::cleanup() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return Void();
}
Return<bool> Gnss::injectTime(int64_t, int64_t, int32_t) {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return bool{};
}
Return<bool> Gnss::injectLocation(double, double, float) {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return bool{};
}
Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData) {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return Void();
}
Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode,
V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t,
uint32_t) {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return bool{};
}
Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_0::IAGnssRil>{};
}
Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_0::IGnssGeofencing>{};
}
Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_0::IAGnss>{};
}
@@ -131,27 +152,27 @@
}
Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_0::IGnssNavigationMessage>{};
}
Return<sp<V1_0::IGnssXtra>> Gnss::getExtensionXtra() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_0::IGnssXtra>{};
}
Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_0::IGnssConfiguration>{};
}
Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_0::IGnssDebug>{};
}
Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_0::IGnssBatching>{};
}
@@ -194,7 +215,7 @@
}
Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<V1_1::IGnssConfiguration>{};
}
@@ -204,7 +225,7 @@
}
Return<bool> Gnss::injectBestLocation(const V1_0::GnssLocation&) {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return bool{};
}
@@ -228,7 +249,7 @@
Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
Gnss::getExtensionMeasurementCorrections() {
- // TODO implement
+ // TODO(b/124012850): Implement function.
return sp<measurement_corrections::V1_0::IMeasurementCorrections>{};
}
@@ -268,16 +289,21 @@
return true;
}
-Return<void> Gnss::reportLocation(const GnssLocation& location) const {
+Return<void> Gnss::reportLocation(const V2_0::GnssLocation& location) const {
std::unique_lock<std::mutex> lock(mMutex);
- if (sGnssCallback_1_1 == nullptr) {
- ALOGE("%s: sGnssCallback is null.", __func__);
+ if (sGnssCallback_2_0 == nullptr) {
+ ALOGE("%s: sGnssCallback 2.0 is null.", __func__);
return Void();
}
- sGnssCallback_1_1->gnssLocationCb(location);
+ sGnssCallback_2_0->gnssLocationCb_2_0(location);
return Void();
}
+Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation&) {
+ // TODO(b/124012850): Implement function.
+ return bool{};
+}
+
} // namespace implementation
} // namespace V2_0
} // namespace gnss
diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h
index 7d9e783..f02ab0a 100644
--- a/gnss/2.0/default/Gnss.h
+++ b/gnss/2.0/default/Gnss.h
@@ -91,15 +91,16 @@
getExtensionMeasurementCorrections() override;
Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
override;
+ Return<bool> injectBestLocation_2_0(const V2_0::GnssLocation& location) override;
- private:
- Return<void> reportLocation(const GnssLocation&) const;
- static sp<V2_0::IGnssCallback> sGnssCallback_2_0;
- static sp<V1_1::IGnssCallback> sGnssCallback_1_1;
- std::atomic<long> mMinIntervalMs;
- std::atomic<bool> mIsActive;
- std::thread mThread;
- mutable std::mutex mMutex;
+ private:
+ Return<void> reportLocation(const V2_0::GnssLocation&) const;
+ static sp<V2_0::IGnssCallback> sGnssCallback_2_0;
+ static sp<V1_1::IGnssCallback> sGnssCallback_1_1;
+ std::atomic<long> mMinIntervalMs;
+ std::atomic<bool> mIsActive;
+ std::thread mThread;
+ mutable std::mutex mMutex;
};
} // namespace implementation
diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp
index 0f707b4..702c9e2 100644
--- a/gnss/2.0/default/GnssMeasurement.cpp
+++ b/gnss/2.0/default/GnssMeasurement.cpp
@@ -16,7 +16,9 @@
#define LOG_TAG "GnssMeasurement"
#include "GnssMeasurement.h"
+
#include <log/log.h>
+#include <utils/SystemClock.h>
namespace android {
namespace hardware {
@@ -129,7 +131,18 @@
.driftNsps = -51.757811607455452,
.driftUncertaintyNsps = 310.64968328491528,
.hwClockDiscontinuityCount = 1};
- GnssData gnssData = {.measurements = measurements, .clock = clock};
+
+ ElapsedRealtime timestamp = {
+ .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+ .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
+ // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+ // In an actual implementation provide an estimate of the synchronization uncertainty
+ // or don't set the field.
+ .timeUncertaintyNs = 1000000};
+
+ GnssData gnssData = {
+ .measurements = measurements, .clock = clock, .elapsedRealtime = timestamp};
return gnssData;
}
diff --git a/gnss/2.0/types.hal b/gnss/2.0/types.hal
index 97c178f..4abb604 100644
--- a/gnss/2.0/types.hal
+++ b/gnss/2.0/types.hal
@@ -16,5 +16,60 @@
package android.hardware.gnss@2.0;
+import @1.0::GnssLocation;
+
/** Network handle type. */
typedef uint64_t net_handle_t;
+
+/**
+ * Flags indicating the validity of the fields in ElapsedRealtime.
+ */
+@export(name="", value_prefix="ELAPSED_REALTIME_")
+enum ElapsedRealtimeFlags : uint16_t {
+ /** A valid timestampNs is stored in the data structure. */
+ HAS_TIMESTAMP_NS = 1 << 0,
+ /** A valid timeUncertaintyNs is stored in the data structure. */
+ HAS_TIME_UNCERTAINTY_NS = 1 << 1,
+};
+
+/**
+ * Represents an estimate of elapsed time since boot of Android for a given event.
+ *
+ * This timestamp MUST represent the time the event happened and MUST be synchronized
+ * with the SystemClock.elapsedRealtimeNanos() clock.
+ */
+struct ElapsedRealtime {
+ /**
+ * A set of flags indicating the validity of each field in this data structure.
+ *
+ * Fields may have invalid information in them, if not marked as valid by the
+ * corresponding bit in flags.
+ */
+ bitfield<ElapsedRealtimeFlags> flags;
+
+ /**
+ * Estimate of the elapsed time since boot value for the corresponding event in nanoseconds.
+ */
+ uint64_t timestampNs;
+
+ /**
+ * Estimate of the relative precision of the alignment of this SystemClock
+ * timestamp, with the reported measurements in nanoseconds (68% confidence).
+ */
+ uint64_t timeUncertaintyNs;
+};
+
+/** Represents a location. */
+struct GnssLocation {
+ @1.0::GnssLocation v1_0;
+
+ /**
+ * Timing information of the GNSS location synchronized with SystemClock.elapsedRealtimeNanos()
+ * clock.
+ *
+ * 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.
+ */
+ ElapsedRealtime elapsedRealtime;
+};
\ No newline at end of file
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index 1580c28..c564f41 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -130,10 +130,10 @@
return false;
}
-void GnssHalTest::CheckLocation(const GnssLocation& location, bool check_speed) {
+void GnssHalTest::CheckLocation(const GnssLocation_2_0& location, bool check_speed) {
const bool check_more_accuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017);
- Utils::checkLocation(location, check_speed, check_more_accuracies);
+ Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies);
}
void GnssHalTest::StartAndCheckLocations(int count) {
@@ -193,6 +193,14 @@
return Void();
}
+Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
+ ALOGI("Capabilities (v2.0) received %d", capabilities);
+ parent_.capabilities_called_count_++;
+ parent_.last_capabilities_ = capabilities;
+ parent_.notify();
+ return Void();
+}
+
Return<void> GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
ALOGI("Name received: %s", name.c_str());
parent_.name_called_count_++;
@@ -201,8 +209,19 @@
return Void();
}
-Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation& location) {
+Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation_1_0& location) {
ALOGI("Location received");
+ GnssLocation_2_0 location_v2_0;
+ location_v2_0.v1_0 = location;
+ return gnssLocationCbImpl(location_v2_0);
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_0& location) {
+ ALOGI("Location (v2.0) received");
+ return gnssLocationCbImpl(location);
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) {
parent_.location_called_count_++;
parent_.last_location_ = location;
parent_.notify();
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index 2c16651..31750a6 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -18,7 +18,6 @@
#define GNSS_HAL_TEST_H_
#include <android/hardware/gnss/2.0/IGnss.h>
-
#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
@@ -29,11 +28,13 @@
using android::hardware::Return;
using android::hardware::Void;
-using android::hardware::gnss::V1_0::GnssLocation;
-
using android::hardware::gnss::V1_0::GnssLocationFlags;
-using android::hardware::gnss::V1_1::IGnssCallback;
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 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;
@@ -97,10 +98,21 @@
Return<void> gnssRequestTimeCb() override { return Void(); }
// Actual (test) callback handlers
Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
- Return<void> gnssLocationCb(const GnssLocation& location) 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;
+
+ // New in v2.0
+ Return<void> gnssLocationCb_2_0(const GnssLocation_2_0& location) override;
+ Return<void> gnssRequestLocationCb_2_0(bool /* independentFromGnss */,
+ bool /* isUserEmergency */) override {
+ return Void();
+ }
+ Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
+
+ private:
+ Return<void> gnssLocationCbImpl(const GnssLocation_2_0& location);
};
/* Callback class for GnssMeasurement. */
@@ -147,7 +159,7 @@
*
* check_speed: true if speed related fields are also verified.
*/
- void CheckLocation(const GnssLocation& location, const bool check_speed);
+ void CheckLocation(const GnssLocation_2_0& location, const bool check_speed);
/*
* StartAndCheckLocations:
@@ -186,7 +198,7 @@
IGnssCallback::GnssSystemInfo last_info_;
uint32_t last_capabilities_;
- GnssLocation last_location_;
+ GnssLocation_2_0 last_location_;
IGnssMeasurementCallback_2_0::GnssData last_measurement_;
android::hardware::hidl_string last_name_;
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 48f2be8..b135dba 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -31,7 +31,9 @@
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 android::hardware::gnss::V1_0::IGnssNi;
+using android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
/*
@@ -269,3 +271,64 @@
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
}
+
+/*
+ * TestGnssDataElapsedRealtimeFlags:
+ * Sets a GnssMeasurementCallback, waits for a GnssData object, and verifies the flags in member
+ * elapsedRealitme are valid.
+ */
+TEST_F(GnssHalTest, TestGnssDataElapsedRealtimeFlags) {
+ const int kFirstGnssMeasurementTimeoutSeconds = 10;
+
+ auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_0();
+ if (!gnssMeasurement.isOk()) {
+ return;
+ }
+
+ sp<IGnssMeasurement_2_0> iGnssMeasurement = gnssMeasurement;
+ if (iGnssMeasurement == nullptr) {
+ return;
+ }
+
+ sp<IGnssMeasurementCallback_2_0> callback = new GnssMeasurementCallback(*this);
+
+ auto result = iGnssMeasurement->setCallback_2_0(callback, /* enableFullTracking= */ true);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS);
+
+ 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);
+
+ // We expect a non-zero timestamp when set.
+ if (last_measurement_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
+ ASSERT_TRUE(last_measurement_.elapsedRealtime.timestampNs != 0);
+ }
+
+ iGnssMeasurement->close();
+}
+
+TEST_F(GnssHalTest, TestGnssLocationElapsedRealtime) {
+ StartAndCheckFirstLocation();
+
+ ASSERT_TRUE((int)last_location_.elapsedRealtime.flags >= 0 &&
+ (int)last_location_.elapsedRealtime.flags <=
+ (int)ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS);
+
+ // We expect a non-zero timestamp when set.
+ if (last_location_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
+ ASSERT_TRUE(last_location_.elapsedRealtime.timestampNs != 0);
+ }
+
+ StopAndClearLocations();
+}
+
+// This test only verify that injectBestLocation_2_0 does not crash.
+TEST_F(GnssHalTest, TestInjectBestLocation_2_0) {
+ StartAndCheckFirstLocation();
+ gnss_hal_->injectBestLocation_2_0(last_location_);
+ StopAndClearLocations();
+}
diff --git a/input/classifier/1.0/vts/OWNERS b/input/classifier/1.0/vts/OWNERS
new file mode 100644
index 0000000..447f3d9
--- /dev/null
+++ b/input/classifier/1.0/vts/OWNERS
@@ -0,0 +1,3 @@
+michaelwr@google.com
+pquinn@google.com
+svv@google.com
\ No newline at end of file
diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..ef49d70
--- /dev/null
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+
+cc_test {
+ name: "VtsHalInputClassifierV1_0TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalInputClassifierV1_0TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.input.classifier@1.0",
+ "android.hardware.input.common@1.0",
+ ],
+ test_suites: ["general-tests"],
+}
+
diff --git a/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp b/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp
new file mode 100644
index 0000000..f033c2a
--- /dev/null
+++ b/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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 "input_classifier_hal_test"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
+#include <android/hardware/input/common/1.0/types.h>
+#include <input/InputDevice.h>
+#include <unistd.h>
+
+using ::android::ReservedInputDeviceId;
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::input::classifier::V1_0::IInputClassifier;
+using ::android::hardware::input::common::V1_0::Action;
+using ::android::hardware::input::common::V1_0::Axis;
+using ::android::hardware::input::common::V1_0::Button;
+using ::android::hardware::input::common::V1_0::EdgeFlag;
+using ::android::hardware::input::common::V1_0::MotionEvent;
+using ::android::hardware::input::common::V1_0::PointerCoords;
+using ::android::hardware::input::common::V1_0::PointerProperties;
+using ::android::hardware::input::common::V1_0::Source;
+using ::android::hardware::input::common::V1_0::ToolType;
+using ::android::hardware::input::common::V1_0::VideoFrame;
+
+static MotionEvent getSimpleMotionEvent() {
+ MotionEvent event;
+ event.action = Action::DOWN;
+ event.actionButton = Button::NONE;
+ event.actionIndex = 0;
+ event.buttonState = 0;
+ event.deviceId = 0;
+ event.deviceTimestamp = 0;
+ event.displayId = 1;
+ event.downTime = 2;
+ event.edgeFlags = 0;
+ event.eventTime = 3;
+ event.flags = 0;
+ event.frames = {};
+ event.metaState = 0;
+ event.policyFlags = 0;
+ event.source = Source::TOUCHSCREEN;
+ event.xPrecision = 0;
+ event.yPrecision = 0;
+
+ PointerCoords coords;
+ coords.bits = Axis::X | Axis::Y;
+ coords.values = {1 /*X*/, 2 /*Y*/};
+ event.pointerCoords = {coords};
+
+ PointerProperties properties;
+ properties.id = 0;
+ properties.toolType = ToolType::FINGER;
+ event.pointerProperties = {properties};
+
+ return event;
+}
+
+// Test environment for Input Classifier HIDL HAL.
+class InputClassifierHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static InputClassifierHidlEnvironment* Instance() {
+ static InputClassifierHidlEnvironment* instance = new InputClassifierHidlEnvironment;
+ return instance;
+ }
+
+ virtual void registerTestServices() override { registerTestService<IInputClassifier>(); }
+
+ private:
+ InputClassifierHidlEnvironment() {}
+};
+
+// The main test class for INPUT CLASSIFIER HIDL HAL 1.0.
+class InputClassifierHidlTest_1_0 : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ classifier = ::testing::VtsHalHidlTargetTestBase::getService<IInputClassifier>(
+ InputClassifierHidlEnvironment::Instance()->getServiceName<IInputClassifier>());
+ ASSERT_NE(classifier, nullptr);
+ }
+
+ virtual void TearDown() override {}
+
+ sp<IInputClassifier> classifier;
+};
+
+/**
+ * Call resetDevice(..) for a few common device id values, and make sure that the HAL
+ * can handle the resets gracefully.
+ */
+TEST_F(InputClassifierHidlTest_1_0, ResetDevice) {
+ EXPECT_TRUE(classifier->resetDevice(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID).isOk());
+ EXPECT_TRUE(classifier->resetDevice(ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID).isOk());
+ EXPECT_TRUE(classifier->resetDevice(1).isOk());
+ EXPECT_TRUE(classifier->resetDevice(2).isOk());
+}
+
+/**
+ * Call reset() on the HAL to ensure no fatal failure there.
+ */
+TEST_F(InputClassifierHidlTest_1_0, ResetHal) {
+ EXPECT_TRUE(classifier->reset().isOk());
+}
+
+/**
+ * Classify an event without any video frames.
+ */
+TEST_F(InputClassifierHidlTest_1_0, Classify_NoVideoFrame) {
+ // Create a MotionEvent that does not have any video data
+ MotionEvent event = getSimpleMotionEvent();
+
+ EXPECT_TRUE(classifier->classify(event).isOk());
+ // We are not checking the actual classification here,
+ // because the HAL operation is highly device-specific.
+
+ // Return HAL to a consistent state by doing a reset
+ classifier->reset();
+}
+
+/**
+ * Classify an event with one video frame. Should be the most common scenario.
+ */
+TEST_F(InputClassifierHidlTest_1_0, Classify_OneVideoFrame) {
+ MotionEvent event = getSimpleMotionEvent();
+ VideoFrame frame;
+ frame.data = {1, 2, 3, 4};
+ frame.height = 2;
+ frame.width = 2;
+ frame.timestamp = event.eventTime;
+ event.frames = {frame};
+
+ EXPECT_TRUE(classifier->classify(event).isOk());
+ // We are not checking the actual classification here,
+ // because the HAL operation is highly device-specific.
+
+ // Return HAL to a consistent state by doing a reset
+ classifier->reset();
+}
+
+/**
+ * Classify an event with 2 video frames. This could happen if there's slowness in the system,
+ * or if simply the video rate is somehow higher that the input event rate.
+ * The HAL should be able to handle events with more than 1 video frame.
+ *
+ * The frames should be in chronological order, but it is not guaranteed that they will have
+ * monotonically increasing timestamps. Still, we provide consistent timestamps here since that
+ * is the most realistic mode of operation.
+ */
+TEST_F(InputClassifierHidlTest_1_0, Classify_TwoVideoFrames) {
+ MotionEvent event = getSimpleMotionEvent();
+ VideoFrame frame1;
+ frame1.data = {1, 2, 3, 4};
+ frame1.height = 2;
+ frame1.width = 2;
+ frame1.timestamp = event.eventTime;
+ VideoFrame frame2 = frame1;
+ frame2.data = {5, 5, 5, -1};
+ frame2.timestamp += 1;
+ event.frames = {frame1, frame2};
+
+ EXPECT_TRUE(classifier->classify(event).isOk());
+ // We are not checking the actual classification here,
+ // because the HAL operation is highly device-specific.
+
+ // Return HAL to a consistent state by doing a reset
+ classifier->reset();
+}
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(InputClassifierHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ InputClassifierHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
+}
diff --git a/input/common/1.0/types.hal b/input/common/1.0/types.hal
index 1a07f3b..9ad368b 100644
--- a/input/common/1.0/types.hal
+++ b/input/common/1.0/types.hal
@@ -685,20 +685,20 @@
* Touch heatmap.
*
* The array is a 2-D row-major matrix with dimensions (height, width).
- * The heatmap data does not rotate when device orientation changes.
+ * The heatmap data is rotated when device orientation changes.
*
* Example:
*
* If the data in the array is:
* data[i] = i for i in 0 .. 59,
- * then it can be represented as follows:
+ * then it can be represented as a 10 x 6 matrix:
*
- * <-- width -- >
+ * <-- width -->
* 0 1 2 3 4 5 ^
* 6 7 8 9 10 11 |
- * 12 12 14 15 16 17 |
- * 18 ... 23 | height
- * 24 ... 29 |
+ * 12 13 14 15 16 17 |
+ * 18 ... 23 |
+ * 24 ... 29 | height
* 30 ... 35 |
* 36 ... 41 |
* 42 ... 47 |
@@ -708,16 +708,33 @@
* Looking at the device in standard portrait orientation,
* the element "0" is the top left of the screen,
* "5" is at the top right, and "59" is the bottom right.
- * Here width=6, and height=10.
+ * Here height=10 and width=6.
+ *
+ * If the screen orientation changes to landscape (a 90 degree orientation
+ * change), the frame's dimensions will become 6 x 10
+ * and the data will look as follows:
+ * 54 48 42 36 30 24 18 12 6 0 ^
+ * ... 13 7 1 |
+ * ... 14 8 2 | height
+ * ... 15 9 3 |
+ * ... 16 10 4 |
+ * 59 53 47 41 35 29 23 17 11 5 v
+ * <-- width -->
+ *
+ * Here the element "0" is at the physical top left of the unrotated screen.
+ *
+ * Since the coordinates of a MotionEvent are also adjusted based on the
+ * orientation, the rotation of the video frame data ensures that
+ * the axes for MotionEvent and VideoFrame data are consistent.
*/
struct VideoFrame {
/**
* Video frame data.
- * Size of the data is width * height.
+ * Size of the data is height * width.
*/
vec<int16_t> data;
- uint32_t width;
uint32_t height;
+ uint32_t width;
/**
* Time at which the frame was collected, in nanoseconds.
* Measured with the same clock that is used to populate MotionEvent times.
diff --git a/power/stats/1.0/types.hal b/power/stats/1.0/types.hal
index 644224b..6051e3f 100644
--- a/power/stats/1.0/types.hal
+++ b/power/stats/1.0/types.hal
@@ -26,9 +26,9 @@
struct RailInfo {
/** Index corresponding to the rail */
uint32_t index;
- /** Name of the rail */
+ /** Name of the rail (opaque to the framework) */
string railName;
- /** Name of the subsystem to which this rail belongs */
+ /** Name of the subsystem to which this rail belongs (opaque to the framework) */
string subsysName;
/** Hardware sampling rate */
uint32_t samplingRate;
@@ -71,7 +71,7 @@
struct PowerEntityInfo {
/** Unique ID corresponding to the PowerEntity */
uint32_t powerEntityId;
- /** Name of the PowerEntity */
+ /** Name of the PowerEntity (opaque to the framework) */
string powerEntityName;
/** Type of the PowerEntity */
PowerEntityType type;
@@ -82,7 +82,7 @@
* ID corresponding to the state. Unique for a given PowerEntityStateSpace
*/
uint32_t powerEntityStateId;
- /** Name of the state */
+ /** Name of the state (opaque to the framework) */
string powerEntityStateName;
};
diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal
index cc5b860..95cf615 100644
--- a/radio/1.3/IRadio.hal
+++ b/radio/1.3/IRadio.hal
@@ -49,10 +49,8 @@
vec<RadioAccessSpecifier> specifiers);
/**
- * Toggle logical modem on and off. It should put the logical modem in low power
- * mode without any activity, while the SIM card remains visible. The difference
- * with setRadioPower is, setRadioPower affects all logical modem while this controls
- * just one.
+ * Toggle logical modem on and off. The difference with setRadioPower is,
+ * setRadioPower affects all logical modems while this controls just one.
*
* @param serial Serial number of request.
* @param on True to turn on the logical modem, otherwise turn it off.
@@ -62,9 +60,8 @@
oneway enableModem(int32_t serial, bool on);
/**
- * Request status of logical modem associated with the given serial number. It returns
- * isEnabled=true if the logical modem is in low power mode without any activity, while
- * the SIM card remains visible.
+ * Request status of logical modem. It returns isEnabled=true if the logical modem is on.
+ * This method is the getter method for enableModem.
*
* @param serial Serial number of request.
*
diff --git a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
index 6208c67..1bebae7 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
@@ -75,3 +75,36 @@
radioRsp_v1_3->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
}
+
+/*
+ * Test IRadio.setSystemSelectionChannels() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_3, setSystemSelectionChannels) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ Return<void> res = radio_v1_3->setSystemSelectionChannels(serial, true, {specifier});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_3->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial);
+ ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+ toString(radioRsp_v1_3->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_3->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+ if (radioRsp_v1_3->rspInfo.error == RadioError::NONE) {
+ Return<void> res = radio_v1_3->setSystemSelectionChannels(serial, false, {specifier});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_3->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial);
+ ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+ toString(radioRsp_v1_3->rspInfo.error).c_str());
+ EXPECT_EQ(RadioError::NONE, radioRsp_v1_3->rspInfo.error);
+ }
+}
\ No newline at end of file
diff --git a/radio/1.3/vts/functional/radio_response.cpp b/radio/1.3/vts/functional/radio_response.cpp
index 900794e..84a9890 100644
--- a/radio/1.3/vts/functional/radio_response.cpp
+++ b/radio/1.3/vts/functional/radio_response.cpp
@@ -769,12 +769,14 @@
/* 1.3 Api */
Return<void> RadioResponse_v1_3::setSystemSelectionChannelsResponse(const RadioResponseInfo& info) {
rspInfo = info;
+ parent_v1_3.notify(info.serial);
return Void();
}
Return<void> RadioResponse_v1_3::enableModemResponse(const RadioResponseInfo& info) {
rspInfo = info;
enableModemResponseToggle = !enableModemResponseToggle;
+ parent_v1_3.notify(info.serial);
return Void();
}
@@ -782,5 +784,6 @@
const bool enabled) {
rspInfo = info;
isModemEnabled = enabled;
+ parent_v1_3.notify(info.serial);
return Void();
}
diff --git a/radio/1.4/IRadio.hal b/radio/1.4/IRadio.hal
index f7ae39f..046f074 100644
--- a/radio/1.4/IRadio.hal
+++ b/radio/1.4/IRadio.hal
@@ -115,11 +115,13 @@
* PUK/PIN state of the subscription and the service state of the radio.
*
* Some countries or carriers require some emergency numbers that must be handled with normal
- * call routing or emergency routing. If the 'routing' field is specified as
- * @1.4::EmergencyNumberRouting#NORMAL, the implementation must use normal call routing to
- * handle the call; if it is specified as @1.4::EmergencyNumberRouting#EMERGENCY, the
- * implementation must use emergency routing to handle the call; if it is
- * @1.4::EmergencyNumberRouting#UNKNOWN, Android does not know how to handle the call.
+ * call routing if possible or emergency routing. 1) if the 'routing' field is specified as
+ * @1.4::EmergencyNumberRouting#NORMAL, the implementation must try the full radio service to
+ * use normal call routing to handle the call; if service cannot support normal routing, the
+ * implementation must use emergency routing to handle the call. 2) if 'routing' is specified
+ * as @1.4::EmergencyNumberRouting#EMERGENCY, the implementation must use emergency routing to
+ * handle the call. 3) if 'routing' is specified as @1.4::EmergencyNumberRouting#UNKNOWN,
+ * Android does not know how to handle the call.
*
* If the dialed emergency number does not have a specified emergency service category, the
* 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED; if the dialed
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index 9237799..15a8acc 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -93,4 +93,473 @@
ALOGI("emergencyDial_withEmergencyRouting, rspInfo.error = %s\n",
toString(radioRsp_v1_4->rspInfo.error).c_str());
EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
-}
\ No newline at end of file
+}
+
+/*
+ * Test IRadio.getPreferredNetworkTypeBitmap() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_4, getPreferredNetworkTypeBitmap) {
+ serial = GetRandomSerialNumber();
+
+ Return<void> res = radio_v1_4->getPreferredNetworkTypeBitmap(serial);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+ ALOGI("getPreferredNetworkTypeBitmap, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+}
+
+TEST_F(RadioHidlTest_v1_4, setPreferredNetworkTypeBitmap) {
+ serial = GetRandomSerialNumber();
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+ network_type_bitmap{};
+
+ network_type_bitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE;
+
+ Return<void> res = radio_v1_4->setPreferredNetworkTypeBitmap(serial, network_type_bitmap);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+ ALOGI("setPreferredNetworkTypeBitmap, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+ if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
+ // give some time for modem to set the value.
+ sleep(3);
+ serial = GetRandomSerialNumber();
+ Return<void> res = radio_v1_4->getPreferredNetworkTypeBitmap(serial);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+ ALOGI("getPreferredNetworkTypeBitmap, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+ EXPECT_EQ(network_type_bitmap, radioRsp_v1_4->networkTypeBitmapResponse);
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT, .interval = 60, .specifiers = {specifier}};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str());
+
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do not support the
+ // required manual GSM search functionality. This is tracked in b/112206766.
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with invalid specifier.
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidArgument) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {.type = ScanType::ONE_SHOT,
+ .interval = 60};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with invalid interval (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 4,
+ .specifiers = {specifier},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_InvalidInterval1, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with invalid interval (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 301,
+ .specifiers = {specifier},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_InvalidInterval2, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with invalid max search time (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 59,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_InvalidMaxSearchTime1, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with invalid max search time (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 3601,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_InvalidMaxSearchTime2, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with invalid periodicity (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 600,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 0};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_InvalidPeriodicity1, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with invalid periodicity (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 600,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 11};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_InvalidPeriodicity2, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with valid periodicity
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ // Some vendor may not support max search time of 360s.
+ // This issue is tracked in b/112205669.
+ .maxSearchTime = 300,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 10};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_GoodRequest1, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan() with valid periodicity and plmns
+ */
+TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+ .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_2::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ // Some vendor may not support max search time of 360s.
+ // This issue is tracked in b/112205669.
+ .maxSearchTime = 300,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 10,
+ .mccMncs = {"310410"}};
+
+ Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("startNetworkScan_GoodRequest2, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+ }
+}
+
+/*
+ * Test IRadio.getSignalStrength_1_4() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_4, getSignalStrength_1_4) {
+ serial = GetRandomSerialNumber();
+
+ radio_v1_4->getSignalStrength_1_4(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+ }
+}
+
+/*
+ * Test IRadio.setupDataCall_1_4() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_4, setupDataCall_1_4) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_4::AccessNetwork accessNetwork =
+ ::android::hardware::radio::V1_4::AccessNetwork::EUTRAN;
+
+ android::hardware::radio::V1_4::DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.profileId = DataProfileId::DEFAULT;
+ dataProfileInfo.apn = hidl_string("internet");
+ dataProfileInfo.protocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.roamingProtocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.user = hidl_string("username");
+ dataProfileInfo.password = hidl_string("password");
+ dataProfileInfo.type = DataProfileInfoType::THREE_GPP;
+ dataProfileInfo.maxConnsTime = 300;
+ dataProfileInfo.maxConns = 20;
+ dataProfileInfo.waitTime = 0;
+ dataProfileInfo.enabled = true;
+ dataProfileInfo.supportedApnTypesBitmap = 320;
+ dataProfileInfo.bearerBitmap = 161543;
+ dataProfileInfo.mtu = 0;
+ dataProfileInfo.preferred = true;
+ dataProfileInfo.persistent = false;
+
+ bool roamingAllowed = false;
+
+ ::android::hardware::radio::V1_2::DataRequestReason reason =
+ ::android::hardware::radio::V1_2::DataRequestReason::NORMAL;
+ std::vector<hidl_string> addresses = {""};
+ std::vector<hidl_string> dnses = {""};
+
+ Return<void> res = radio_v1_4->setupDataCall_1_4(serial, accessNetwork, dataProfileInfo,
+ roamingAllowed, reason, addresses, dnses);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ }
+}
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
index b77814f..ed689c6 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -61,6 +61,9 @@
bool isModemEnabled;
bool enableModemResponseToggle;
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+ networkTypeBitmapResponse;
+
// Data
::android::hardware::radio::V1_4::DataRegStateResult dataRegResp;
diff --git a/radio/1.4/vts/functional/radio_response.cpp b/radio/1.4/vts/functional/radio_response.cpp
index 10ecead..6e9cd43 100644
--- a/radio/1.4/vts/functional/radio_response.cpp
+++ b/radio/1.4/vts/functional/radio_response.cpp
@@ -776,7 +776,6 @@
Return<void> RadioResponse_v1_4::enableModemResponse(const RadioResponseInfo& info) {
rspInfo = info;
- enableModemResponseToggle = !enableModemResponseToggle;
parent_v1_4.notify(info.serial);
return Void();
}
@@ -832,9 +831,9 @@
Return<void> RadioResponse_v1_4::getPreferredNetworkTypeBitmapResponse(
const RadioResponseInfo& info, const ::android::hardware::hidl_bitfield<
::android::hardware::radio::V1_4::RadioAccessFamily>
- /*networkTypeBitmap*/) {
+ networkTypeBitmap) {
rspInfo = info;
- // TODO: may need a new member for bitfield networkTypeBitmap.
+ networkTypeBitmapResponse = networkTypeBitmap;
parent_v1_4.notify(info.serial);
return Void();
}
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
index a1639d8..122ce58 100644
--- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
@@ -69,3 +69,89 @@
ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
+
+/*
+ * Test IRadioConfig.getPhoneCapability()
+ */
+TEST_F(RadioConfigHidlTest, getPhoneCapability) {
+ serial = GetRandomSerialNumber();
+ Return<void> res = radioConfig->getPhoneCapability(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+ EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+ ALOGI("getPhoneCapability, rspInfo.error = %s\n",
+ toString(radioConfigRsp->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioConfigRsp->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+ if (radioConfigRsp->rspInfo.error == RadioError ::NONE) {
+ // maxActiveData should be greater than or equal to maxActiveInternetData.
+ EXPECT_GE(radioConfigRsp->phoneCap.maxActiveData,
+ radioConfigRsp->phoneCap.maxActiveInternetData);
+ // maxActiveData and maxActiveInternetData should be 0 or positive numbers.
+ EXPECT_GE(radioConfigRsp->phoneCap.maxActiveInternetData, 0);
+ }
+}
+
+/*
+ * Test IRadioConfig.getPhoneCapability()
+ */
+TEST_F(RadioConfigHidlTest, setPreferredDataModem) {
+ serial = GetRandomSerialNumber();
+ Return<void> res = radioConfig->getPhoneCapability(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+ EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+ ALOGI("getPhoneCapability, rspInfo.error = %s\n",
+ toString(radioConfigRsp->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioConfigRsp->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+ if (radioConfigRsp->rspInfo.error != RadioError ::NONE) {
+ return;
+ }
+
+ if (radioConfigRsp->phoneCap.logicalModemList.size() == 0) {
+ return;
+ }
+
+ // We get phoneCapability. send setPreferredDataModem command
+ serial = GetRandomSerialNumber();
+ uint8_t modemId = radioConfigRsp->phoneCap.logicalModemList[0].modemId;
+ res = radioConfig->setPreferredDataModem(serial, modemId);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+ EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+ ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioConfigRsp->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+}
+
+/*
+ * Test IRadioConfig.getPhoneCapability()
+ */
+TEST_F(RadioConfigHidlTest, setPreferredDataModem_invalidArgument) {
+ serial = GetRandomSerialNumber();
+ uint8_t modemId = -1;
+ Return<void> res = radioConfig->setPreferredDataModem(serial, modemId);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+ EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+ ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::INTERNAL_ERR}));
+}
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
index 1747ce8..c980901 100644
--- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
@@ -51,6 +51,7 @@
public:
RadioResponseInfo rspInfo;
+ PhoneCapability phoneCap;
RadioConfigResponse(RadioConfigHidlTest& parent);
virtual ~RadioConfigResponse() = default;
diff --git a/radio/config/1.1/vts/functional/radio_config_response.cpp b/radio/config/1.1/vts/functional/radio_config_response.cpp
index 8c9e4d7..ce3dfdf 100644
--- a/radio/config/1.1/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.1/vts/functional/radio_config_response.cpp
@@ -31,7 +31,10 @@
}
Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
- const RadioResponseInfo& /* info */, const PhoneCapability& /* phoneCapability */) {
+ const RadioResponseInfo& info, const PhoneCapability& phoneCapability) {
+ rspInfo = info;
+ phoneCap = phoneCapability;
+ parent.notify(info.serial);
return Void();
}
@@ -47,4 +50,4 @@
Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) {
return Void();
-}
\ No newline at end of file
+}
diff --git a/thermal/2.0/IThermal.hal b/thermal/2.0/IThermal.hal
index f890694..3ea4590 100644
--- a/thermal/2.0/IThermal.hal
+++ b/thermal/2.0/IThermal.hal
@@ -56,22 +56,24 @@
* they go offline, if these devices exist on boot. The method
* always returns and never removes such temperatures. The thresholds
* are returned as static values and must not change across calls. The actual
- * throttling state is determined in driver and HAL and must not be simply
- * compared with these thresholds. To get accurate throttling status, use
- * getCurrentTemperatures or registerThermalChangedCallback and listen.
+ * throttling state is determined in device thermal mitigation policy/agorithm
+ * which might not be simple thresholds so these values Thermal HAL provided
+ * may not be accurate to detemin the throttling status. To get accurate
+ * throttling status, use getCurrentTemperatures or registerThermalChangedCallback
+ * and listen to the callback.
*/
getTemperatureThresholds(bool filterType, TemperatureType type)
generates (ThermalStatus status, vec<TemperatureThreshold> temperatureThresholds);
/**
* Register an IThermalChangedCallback, used by the Thermal HAL
- * to send thermal events when thermal mitigation status changed.
+ * to receive thermal events when thermal mitigation status changed.
* Multiple registrations with different IThermalChangedCallback must be allowed.
* Multiple registrations with same IThermalChangedCallback is not allowed, client
* should unregister the given IThermalChangedCallback first.
*
- * @param callback the IThermalChangedCallback to use for sending
- * thermal events (cannot be nullptr).
+ * @param callback the IThermalChangedCallback to use for receiving
+ * thermal events (nullptr callback will lead to failure with status code FAILURE).
* @param filterType if filter for given sensor type.
* @param type the type to be filtered.
*
@@ -84,11 +86,11 @@
generates (ThermalStatus status);
/**
- * Register an IThermalChangedCallback, used by the Thermal HAL
- * to send thermal events when thermal mitigation status changed.
+ * Unregister an IThermalChangedCallback, used by the Thermal HAL
+ * to receive thermal events when thermal mitigation status changed.
*
- * @param callback the IThermalChangedCallback to use for sending
- * thermal events, or nullptr to set no callback.
+ * @param callback the IThermalChangedCallback used for receiving
+ * thermal events (nullptr callback will lead to failure with status code FAILURE).
*
* @return status Status of the operation. If status code is FAILURE,
* the status.debugMessage must be populated with a human-readable error message.
diff --git a/thermal/2.0/default/Thermal.cpp b/thermal/2.0/default/Thermal.cpp
index 442af61..0ef4b63 100644
--- a/thermal/2.0/default/Thermal.cpp
+++ b/thermal/2.0/default/Thermal.cpp
@@ -155,7 +155,15 @@
bool filterType, TemperatureType type,
registerThermalChangedCallback_cb _hidl_cb) {
ThermalStatus status;
- status.code = ThermalStatusCode::SUCCESS;
+ if (callback == nullptr) {
+ status.code = ThermalStatusCode::FAILURE;
+ status.debugMessage = "Invalid nullptr callback";
+ LOG(ERROR) << status.debugMessage;
+ _hidl_cb(status);
+ return Void();
+ } else {
+ status.code = ThermalStatusCode::SUCCESS;
+ }
std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
if (std::any_of(callbacks_.begin(), callbacks_.end(), [&](const CallbackSetting& c) {
return interfacesEqual(c.callback, callback);
@@ -175,7 +183,15 @@
Return<void> Thermal::unregisterThermalChangedCallback(
const sp<IThermalChangedCallback>& callback, unregisterThermalChangedCallback_cb _hidl_cb) {
ThermalStatus status;
- status.code = ThermalStatusCode::SUCCESS;
+ if (callback == nullptr) {
+ status.code = ThermalStatusCode::FAILURE;
+ status.debugMessage = "Invalid nullptr callback";
+ LOG(ERROR) << status.debugMessage;
+ _hidl_cb(status);
+ return Void();
+ } else {
+ status.code = ThermalStatusCode::SUCCESS;
+ }
bool removed = false;
std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
callbacks_.erase(
diff --git a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
index 3893014..cc2f3df 100644
--- a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
+++ b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
@@ -132,8 +132,13 @@
TEST_F(ThermalHidlTest, RegisterThermalChangedCallbackTest) {
// Expect to fail with same callback
auto ret = mThermal->registerThermalChangedCallback(
- mThermalCallback, false, TemperatureType::SKIN,
- [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+ mThermalCallback, false, TemperatureType::SKIN,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail with null callback
+ ret = mThermal->registerThermalChangedCallback(
+ nullptr, false, TemperatureType::SKIN,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); });
ASSERT_TRUE(ret.isOk());
sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
// Expect to succeed with different callback
@@ -141,11 +146,16 @@
localThermalCallback, false, TemperatureType::SKIN,
[](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
ASSERT_TRUE(ret.isOk());
- // Remove the local callback.
+ // Remove the local callback
ret = mThermal->unregisterThermalChangedCallback(
localThermalCallback,
[](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
ASSERT_TRUE(ret.isOk());
+ // Expect to fail with null callback
+ ret = mThermal->unregisterThermalChangedCallback(nullptr, [](ThermalStatus status) {
+ EXPECT_EQ(ThermalStatusCode::FAILURE, status.code);
+ });
+ ASSERT_TRUE(ret.isOk());
}
// Test Thermal->unregisterThermalChangedCallback.
diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk
index 01fa934..199ea3b 100644
--- a/wifi/1.3/default/Android.mk
+++ b/wifi/1.3/default/Android.mk
@@ -33,6 +33,9 @@
ifdef WIFI_HIDL_FEATURE_DISABLE_AP
LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP
endif
+ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
+LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
+endif
# Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
LOCAL_SRC_FILES := \
@@ -43,6 +46,7 @@
wifi_ap_iface.cpp \
wifi_chip.cpp \
wifi_feature_flags.cpp \
+ wifi_iface_util.cpp \
wifi_legacy_hal.cpp \
wifi_legacy_hal_stubs.cpp \
wifi_mode_controller.cpp \
@@ -139,10 +143,13 @@
tests/hidl_struct_util_unit_tests.cpp \
tests/main.cpp \
tests/mock_wifi_feature_flags.cpp \
+ tests/mock_wifi_iface_util.cpp \
tests/mock_wifi_legacy_hal.cpp \
tests/mock_wifi_mode_controller.cpp \
tests/ringbuffer_unit_tests.cpp \
- tests/wifi_chip_unit_tests.cpp
+ tests/wifi_ap_iface_unit_tests.cpp \
+ tests/wifi_chip_unit_tests.cpp \
+ tests/wifi_iface_util_unit_tests.cpp
LOCAL_STATIC_LIBRARIES := \
libgmock \
libgtest \
diff --git a/wifi/1.3/default/service.cpp b/wifi/1.3/default/service.cpp
index 5daf659..73015cf 100644
--- a/wifi/1.3/default/service.cpp
+++ b/wifi/1.3/default/service.cpp
@@ -30,6 +30,7 @@
using android::hardware::LazyServiceRegistrar;
using android::hardware::wifi::V1_3::implementation::feature_flags::
WifiFeatureFlags;
+using android::hardware::wifi::V1_3::implementation::iface_util::WifiIfaceUtil;
using android::hardware::wifi::V1_3::implementation::legacy_hal::WifiLegacyHal;
using android::hardware::wifi::V1_3::implementation::mode_controller::
WifiModeController;
@@ -52,6 +53,7 @@
new android::hardware::wifi::V1_3::implementation::Wifi(
std::make_shared<WifiLegacyHal>(),
std::make_shared<WifiModeController>(),
+ std::make_shared<WifiIfaceUtil>(),
std::make_shared<WifiFeatureFlags>());
if (kLazyService) {
LazyServiceRegistrar registrar;
diff --git a/wifi/1.3/default/tests/mock_wifi_feature_flags.h b/wifi/1.3/default/tests/mock_wifi_feature_flags.h
index 8b0baa4..ee12b54 100644
--- a/wifi/1.3/default/tests/mock_wifi_feature_flags.h
+++ b/wifi/1.3/default/tests/mock_wifi_feature_flags.h
@@ -34,6 +34,7 @@
MockWifiFeatureFlags();
MOCK_METHOD0(getChipModes, std::vector<V1_0::IWifiChip::ChipMode>());
+ MOCK_METHOD0(isApMacRandomizationDisabled, bool());
};
} // namespace feature_flags
diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp
new file mode 100644
index 0000000..706cb6a
--- /dev/null
+++ b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "mock_wifi_iface_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_3 {
+namespace implementation {
+namespace iface_util {
+
+MockWifiIfaceUtil::MockWifiIfaceUtil() : WifiIfaceUtil() {}
+} // namespace iface_util
+} // namespace implementation
+} // namespace V1_3
+} // namespace wifi
+} // namespace hardware
+} // namespace android
diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.h b/wifi/1.3/default/tests/mock_wifi_iface_util.h
new file mode 100644
index 0000000..87ab5db
--- /dev/null
+++ b/wifi/1.3/default/tests/mock_wifi_iface_util.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef MOCK_WIFI_IFACE_UTIL_H_
+#define MOCK_WIFI_IFACE_UTIL_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_iface_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_3 {
+namespace implementation {
+namespace iface_util {
+
+class MockWifiIfaceUtil : public WifiIfaceUtil {
+ public:
+ MockWifiIfaceUtil();
+ MOCK_METHOD1(getFactoryMacAddress,
+ std::array<uint8_t, 6>(const std::string&));
+ MOCK_METHOD2(setMacAddress,
+ bool(const std::string&, const std::array<uint8_t, 6>&));
+ MOCK_METHOD0(getOrCreateRandomMacAddress, std::array<uint8_t, 6>());
+};
+} // namespace iface_util
+} // namespace implementation
+} // namespace V1_3
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+
+#endif // MOCK_WIFI_IFACE_UTIL_H_
diff --git a/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp
new file mode 100644
index 0000000..28e028b
--- /dev/null
+++ b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <cutils/properties.h>
+#include <gmock/gmock.h>
+
+#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "wifi_ap_iface.h"
+
+#include "mock_wifi_feature_flags.h"
+#include "mock_wifi_iface_util.h"
+#include "mock_wifi_legacy_hal.h"
+
+using testing::NiceMock;
+using testing::Return;
+using testing::Test;
+
+namespace {
+constexpr char kIfaceName[] = "mockWlan0";
+} // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_3 {
+namespace implementation {
+
+class WifiApIfaceTest : public Test {
+ protected:
+ std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+ new NiceMock<legacy_hal::MockWifiLegacyHal>};
+ std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+ new NiceMock<iface_util::MockWifiIfaceUtil>};
+ std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
+ feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
+};
+
+TEST_F(WifiApIfaceTest, SetRandomMacAddressIfFeatureEnabled) {
+ EXPECT_CALL(*feature_flags_, isApMacRandomizationDisabled())
+ .WillOnce(testing::Return(false));
+ EXPECT_CALL(*iface_util_, getOrCreateRandomMacAddress())
+ .WillOnce(testing::Return(std::array<uint8_t, 6>{0, 0, 0, 0, 0, 0}));
+ EXPECT_CALL(*iface_util_, setMacAddress(testing::_, testing::_))
+ .WillOnce(testing::Return(true));
+ sp<WifiApIface> ap_iface =
+ new WifiApIface(kIfaceName, legacy_hal_, iface_util_, feature_flags_);
+}
+
+TEST_F(WifiApIfaceTest, DontSetRandomMacAddressIfFeatureDisabled) {
+ EXPECT_CALL(*feature_flags_, isApMacRandomizationDisabled())
+ .WillOnce(testing::Return(true));
+ EXPECT_CALL(*iface_util_, getOrCreateRandomMacAddress()).Times(0);
+ EXPECT_CALL(*iface_util_, setMacAddress(testing::_, testing::_)).Times(0);
+ sp<WifiApIface> ap_iface =
+ new WifiApIface(kIfaceName, legacy_hal_, iface_util_, feature_flags_);
+}
+} // namespace implementation
+} // namespace V1_3
+} // namespace wifi
+} // namespace hardware
+} // namespace android
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 3fcc39e..134563c 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -23,6 +23,7 @@
#include "wifi_chip.h"
#include "mock_wifi_feature_flags.h"
+#include "mock_wifi_iface_util.h"
#include "mock_wifi_legacy_hal.h"
#include "mock_wifi_mode_controller.h"
@@ -263,7 +264,7 @@
public:
void SetUp() override {
chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
- feature_flags_);
+ iface_util_, feature_flags_);
EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
.WillRepeatedly(testing::Return(true));
@@ -278,6 +279,8 @@
new NiceMock<legacy_hal::MockWifiLegacyHal>};
std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
+ std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+ new NiceMock<iface_util::MockWifiIfaceUtil>};
std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
};
diff --git a/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp
new file mode 100644
index 0000000..e5758fa
--- /dev/null
+++ b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN
+#include "wifi_iface_util.h"
+
+using testing::Test;
+
+namespace {
+constexpr uint8_t kValidUnicastLocallyAssignedMacAddressMask = 0x02;
+
+bool isValidUnicastLocallyAssignedMacAddress(
+ const std::array<uint8_t, 6>& mac_address) {
+ uint8_t first_byte = mac_address[0];
+ return (first_byte & 0x3) == kValidUnicastLocallyAssignedMacAddressMask;
+}
+} // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_3 {
+namespace implementation {
+class WifiIfaceUtilTest : public Test {
+ protected:
+ iface_util::WifiIfaceUtil iface_util_;
+};
+
+TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) {
+ auto mac_address = iface_util_.getOrCreateRandomMacAddress();
+ ASSERT_TRUE(isValidUnicastLocallyAssignedMacAddress(mac_address));
+
+ // All further calls should return the same MAC address.
+ ASSERT_EQ(mac_address, iface_util_.getOrCreateRandomMacAddress());
+ ASSERT_EQ(mac_address, iface_util_.getOrCreateRandomMacAddress());
+}
+} // namespace implementation
+} // namespace V1_3
+} // namespace wifi
+} // namespace hardware
+} // namespace android
diff --git a/wifi/1.3/default/wifi.cpp b/wifi/1.3/default/wifi.cpp
index e3af1ea..1f64085 100644
--- a/wifi/1.3/default/wifi.cpp
+++ b/wifi/1.3/default/wifi.cpp
@@ -36,9 +36,11 @@
Wifi::Wifi(
const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
+ const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
: legacy_hal_(legacy_hal),
mode_controller_(mode_controller),
+ iface_util_(iface_util),
feature_flags_(feature_flags),
run_state_(RunState::STOPPED) {}
@@ -105,7 +107,7 @@
if (wifi_status.code == WifiStatusCode::SUCCESS) {
// Create the chip instance once the HAL is started.
chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
- feature_flags_);
+ iface_util_, feature_flags_);
run_state_ = RunState::STARTED;
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onStart().isOk()) {
diff --git a/wifi/1.3/default/wifi.h b/wifi/1.3/default/wifi.h
index e921424..c4ab773 100644
--- a/wifi/1.3/default/wifi.h
+++ b/wifi/1.3/default/wifi.h
@@ -43,6 +43,7 @@
Wifi(const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::shared_ptr<mode_controller::WifiModeController>
mode_controller,
+ const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags);
bool isValid();
@@ -78,6 +79,7 @@
// and shared with all the child HIDL interface objects.
std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
+ std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_;
std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
RunState run_state_;
sp<WifiChip> chip_;
diff --git a/wifi/1.3/default/wifi_ap_iface.cpp b/wifi/1.3/default/wifi_ap_iface.cpp
index c203e47..9a8681a 100644
--- a/wifi/1.3/default/wifi_ap_iface.cpp
+++ b/wifi/1.3/default/wifi_ap_iface.cpp
@@ -30,8 +30,27 @@
WifiApIface::WifiApIface(
const std::string& ifname,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
- : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util,
+ const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags)
+ : ifname_(ifname),
+ legacy_hal_(legacy_hal),
+ iface_util_(iface_util),
+ feature_flags_(feature_flags),
+ is_valid_(true) {
+ if (feature_flags_.lock()->isApMacRandomizationDisabled()) {
+ LOG(INFO) << "AP MAC randomization disabled";
+ return;
+ }
+ LOG(INFO) << "AP MAC randomization enabled";
+ // Set random MAC address
+ std::array<uint8_t, 6> randomized_mac =
+ iface_util_.lock()->getOrCreateRandomMacAddress();
+ bool status = iface_util_.lock()->setMacAddress(ifname_, randomized_mac);
+ if (!status) {
+ LOG(ERROR) << "Failed to set random mac address";
+ }
+}
void WifiApIface::invalidate() {
legacy_hal_.reset();
diff --git a/wifi/1.3/default/wifi_ap_iface.h b/wifi/1.3/default/wifi_ap_iface.h
index 9f3d870..98c5c9c 100644
--- a/wifi/1.3/default/wifi_ap_iface.h
+++ b/wifi/1.3/default/wifi_ap_iface.h
@@ -20,6 +20,8 @@
#include <android-base/macros.h>
#include <android/hardware/wifi/1.0/IWifiApIface.h>
+#include "wifi_feature_flags.h"
+#include "wifi_iface_util.h"
#include "wifi_legacy_hal.h"
namespace android {
@@ -34,8 +36,11 @@
*/
class WifiApIface : public V1_0::IWifiApIface {
public:
- WifiApIface(const std::string& ifname,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+ WifiApIface(
+ const std::string& ifname,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util,
+ const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags);
// Refer to |WifiChip::invalidate()|.
void invalidate();
bool isValid();
@@ -59,6 +64,8 @@
std::string ifname_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
+ std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
bool is_valid_;
DISALLOW_COPY_AND_ASSIGN(WifiApIface);
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index e7ebc3b..906f14a 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -313,10 +313,12 @@
WifiChip::WifiChip(
ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util,
const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags)
: chip_id_(chip_id),
legacy_hal_(legacy_hal),
mode_controller_(mode_controller),
+ iface_util_(iface_util),
feature_flags_(feature_flags),
is_valid_(true),
current_mode_id_(feature_flags::chip_mode_ids::kInvalid),
@@ -775,7 +777,8 @@
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
std::string ifname = allocateApOrStaIfaceName();
- sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_);
+ sp<WifiApIface> iface =
+ new WifiApIface(ifname, legacy_hal_, iface_util_, feature_flags_);
ap_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
@@ -914,7 +917,7 @@
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
std::string ifname = allocateApOrStaIfaceName();
- sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_);
+ sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_, iface_util_);
sta_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h
index d14ced6..3eb0aee 100644
--- a/wifi/1.3/default/wifi_chip.h
+++ b/wifi/1.3/default/wifi_chip.h
@@ -53,6 +53,7 @@
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<mode_controller::WifiModeController>
mode_controller,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util,
const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags);
// HIDL does not provide a built-in mechanism to let the server invalidate
// a HIDL interface object after creation. If any client process holds onto
@@ -233,6 +234,7 @@
ChipId chip_id_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
+ std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
std::vector<sp<WifiApIface>> ap_ifaces_;
std::vector<sp<WifiNanIface>> nan_ifaces_;
diff --git a/wifi/1.3/default/wifi_feature_flags.cpp b/wifi/1.3/default/wifi_feature_flags.cpp
index 17b3bee..7212cfa 100644
--- a/wifi/1.3/default/wifi_feature_flags.cpp
+++ b/wifi/1.3/default/wifi_feature_flags.cpp
@@ -144,12 +144,22 @@
#undef P2P
#undef NAN
+#ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
+static const bool wifiHidlFeatureDisableApMacRandomization = true;
+#else
+static const bool wifiHidlFeatureDisableApMacRandomization = false;
+#endif // WIFI_HIDL_FEATURE_DISABLE_AP
+
WifiFeatureFlags::WifiFeatureFlags() {}
std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes() {
return kChipModes;
}
+bool WifiFeatureFlags::isApMacRandomizationDisabled() {
+ return wifiHidlFeatureDisableApMacRandomization;
+}
+
} // namespace feature_flags
} // namespace implementation
} // namespace V1_3
diff --git a/wifi/1.3/default/wifi_feature_flags.h b/wifi/1.3/default/wifi_feature_flags.h
index b99a416..3ae6920 100644
--- a/wifi/1.3/default/wifi_feature_flags.h
+++ b/wifi/1.3/default/wifi_feature_flags.h
@@ -43,6 +43,7 @@
virtual ~WifiFeatureFlags() = default;
virtual std::vector<V1_0::IWifiChip::ChipMode> getChipModes();
+ virtual bool isApMacRandomizationDisabled();
};
} // namespace feature_flags
diff --git a/wifi/1.3/default/wifi_iface_util.cpp b/wifi/1.3/default/wifi_iface_util.cpp
new file mode 100644
index 0000000..5d61271
--- /dev/null
+++ b/wifi/1.3/default/wifi_iface_util.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#include <cstddef>
+#include <iostream>
+#include <limits>
+#include <random>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <private/android_filesystem_config.h>
+
+#undef NAN
+#include "wifi_iface_util.h"
+
+namespace {
+// Constants to set the local bit & clear the multicast bit.
+constexpr uint8_t kMacAddressMulticastMask = 0x01;
+constexpr uint8_t kMacAddressLocallyAssignedMask = 0x02;
+} // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_3 {
+namespace implementation {
+namespace iface_util {
+
+WifiIfaceUtil::WifiIfaceUtil() : random_mac_address_(nullptr) {}
+
+std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(
+ const std::string& iface_name) {
+ return iface_tool_.GetFactoryMacAddress(iface_name.c_str());
+}
+
+bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
+ const std::array<uint8_t, 6>& mac) {
+ if (!iface_tool_.SetUpState(iface_name.c_str(), false)) {
+ LOG(ERROR) << "SetUpState(false) failed.";
+ return false;
+ }
+ if (!iface_tool_.SetMacAddress(iface_name.c_str(), mac)) {
+ LOG(ERROR) << "SetMacAddress failed.";
+ return false;
+ }
+ if (!iface_tool_.SetUpState(iface_name.c_str(), true)) {
+ LOG(ERROR) << "SetUpState(true) failed.";
+ return false;
+ }
+ LOG(DEBUG) << "Successfully SetMacAddress.";
+ return true;
+}
+
+std::array<uint8_t, 6> WifiIfaceUtil::getOrCreateRandomMacAddress() {
+ if (random_mac_address_) {
+ return *random_mac_address_.get();
+ }
+ random_mac_address_ =
+ std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress());
+ return *random_mac_address_.get();
+}
+
+std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() {
+ std::array<uint8_t, 6> address = {};
+ std::random_device rd;
+ std::default_random_engine engine(rd());
+ std::uniform_int_distribution<uint8_t> dist(
+ std::numeric_limits<uint8_t>::min(),
+ std::numeric_limits<uint8_t>::max());
+ for (size_t i = 0; i < address.size(); i++) {
+ address[i] = dist(engine);
+ }
+ // Set the local bit and clear the multicast bit.
+ address[0] |= kMacAddressLocallyAssignedMask;
+ address[0] &= ~kMacAddressMulticastMask;
+ return address;
+}
+} // namespace iface_util
+} // namespace implementation
+} // namespace V1_3
+} // namespace wifi
+} // namespace hardware
+} // namespace android
diff --git a/wifi/1.3/default/wifi_iface_util.h b/wifi/1.3/default/wifi_iface_util.h
new file mode 100644
index 0000000..b238234
--- /dev/null
+++ b/wifi/1.3/default/wifi_iface_util.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef WIFI_IFACE_UTIL_H_
+#define WIFI_IFACE_UTIL_H_
+
+#include <wifi_system/interface_tool.h>
+
+#include <android/hardware/wifi/1.0/IWifi.h>
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_3 {
+namespace implementation {
+namespace iface_util {
+
+/**
+ * Util class for common iface operations.
+ */
+class WifiIfaceUtil {
+ public:
+ WifiIfaceUtil();
+ virtual ~WifiIfaceUtil() = default;
+
+ virtual std::array<uint8_t, 6> getFactoryMacAddress(
+ const std::string& iface_name);
+ virtual bool setMacAddress(const std::string& iface_name,
+ const std::array<uint8_t, 6>& mac);
+ // Get or create a random MAC address. The MAC address returned from
+ // this method will remain the same throughout the lifetime of the HAL
+ // daemon. (So, changes on every reboot)
+ virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress();
+
+ private:
+ std::array<uint8_t, 6> createRandomMacAddress();
+
+ wifi_system::InterfaceTool iface_tool_;
+ std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
+};
+
+} // namespace iface_util
+} // namespace implementation
+} // namespace V1_3
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+
+#endif // WIFI_IFACE_UTIL_H_
diff --git a/wifi/1.3/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp
index f7157a3..17f3e3d 100644
--- a/wifi/1.3/default/wifi_sta_iface.cpp
+++ b/wifi/1.3/default/wifi_sta_iface.cpp
@@ -30,8 +30,12 @@
WifiStaIface::WifiStaIface(
const std::string& ifname,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
- : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+ : ifname_(ifname),
+ legacy_hal_(legacy_hal),
+ iface_util_(iface_util),
+ is_valid_(true) {
// Turn on DFS channel usage for STA iface.
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->setDfsFlag(ifname_, true);
@@ -622,28 +626,17 @@
WifiStatus WifiStaIface::setMacAddressInternal(
const std::array<uint8_t, 6>& mac) {
- if (!iface_tool_.SetWifiUpState(false)) {
- LOG(ERROR) << "SetWifiUpState(false) failed.";
+ bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
+ if (!status) {
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
-
- if (!iface_tool_.SetMacAddress(ifname_.c_str(), mac)) {
- LOG(ERROR) << "SetMacAddress failed.";
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
-
- if (!iface_tool_.SetWifiUpState(true)) {
- LOG(ERROR) << "SetWifiUpState(true) failed.";
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- LOG(DEBUG) << "Successfully SetMacAddress.";
return createWifiStatus(WifiStatusCode::SUCCESS);
}
std::pair<WifiStatus, std::array<uint8_t, 6>>
WifiStaIface::getFactoryMacAddressInternal() {
std::array<uint8_t, 6> mac =
- iface_tool_.GetFactoryMacAddress(ifname_.c_str());
+ iface_util_.lock()->getFactoryMacAddress(ifname_);
return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
}
diff --git a/wifi/1.3/default/wifi_sta_iface.h b/wifi/1.3/default/wifi_sta_iface.h
index 69cb82a..9224939 100644
--- a/wifi/1.3/default/wifi_sta_iface.h
+++ b/wifi/1.3/default/wifi_sta_iface.h
@@ -21,9 +21,8 @@
#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
#include <android/hardware/wifi/1.3/IWifiStaIface.h>
-#include <wifi_system/interface_tool.h>
-
#include "hidl_callback_util.h"
+#include "wifi_iface_util.h"
#include "wifi_legacy_hal.h"
namespace android {
@@ -39,7 +38,8 @@
class WifiStaIface : public V1_3::IWifiStaIface {
public:
WifiStaIface(const std::string& ifname,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
// Refer to |WifiChip::invalidate()|.
void invalidate();
bool isValid();
@@ -162,10 +162,10 @@
std::string ifname_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
bool is_valid_;
hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback>
event_cb_handler_;
- wifi_system::InterfaceTool iface_tool_;
DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
};