Merge "Add number of ticks in HW_KEY_INPUT" into qt-dev
diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal
index e1279ee..33a8d62 100644
--- a/audio/common/5.0/types.hal
+++ b/audio/common/5.0/types.hal
@@ -331,7 +331,13 @@
/**
* A channel mask per se only defines the presence or absence of a channel, not
- * the order. See AUDIO_INTERLEAVE_* for the platform convention of order.
+ * the order.
+ *
+ * The channel order convention is that channels are interleaved in order from
+ * least significant channel mask bit to most significant channel mask bit,
+ * with unused bits skipped. For example for stereo, LEFT would be first,
+ * followed by RIGHT.
+ * Any exceptions to this convention are noted at the appropriate API.
*
* AudioChannelMask is an opaque type and its internal layout should not be
* assumed as it may change in the future. Instead, always use functions
diff --git a/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h b/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h
new file mode 100644
index 0000000..b514a43
--- /dev/null
+++ b/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h
@@ -0,0 +1,34 @@
+/*
+ * 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 android_hardware_audio_common_HidlSupport_H_
+#define android_hardware_audio_common_HidlSupport_H_
+
+
+#include <hidl/HidlSupport.h>
+#include <algorithm>
+
+namespace android::hardware::audio::common::utils {
+
+template <typename Enum>
+bool isValidHidlEnum(Enum e) {
+ hidl_enum_range<Enum> values;
+ return std::find(values.begin(), values.end(), e) != values.end();
+}
+
+} // namespace android::hardware::audio::common::utils
+
+#endif // android_hardware_audio_common_HidlSupport_H_
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index daba6f7..d316f83 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -19,6 +19,7 @@
#include "core/default/StreamIn.h"
#include "core/default/Conversions.h"
#include "core/default/Util.h"
+#include "common/all-versions/HidlSupport.h"
//#define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_AUDIO
@@ -27,6 +28,7 @@
#include <hardware/audio.h>
#include <utils/Trace.h>
#include <memory>
+#include <cmath>
namespace android {
namespace hardware {
@@ -501,6 +503,10 @@
if (mStream->set_microphone_direction == nullptr) {
return Result::NOT_SUPPORTED;
}
+ if (!common::utils::isValidHidlEnum(direction)) {
+ ALOGE("%s: Invalid direction %d", __func__, direction);
+ return Result::INVALID_ARGUMENTS;
+ }
return Stream::analyzeStatus(
"set_microphone_direction",
mStream->set_microphone_direction(
@@ -511,6 +517,10 @@
if (mStream->set_microphone_field_dimension == nullptr) {
return Result::NOT_SUPPORTED;
}
+ if (std::isnan(zoom) || zoom < -1 || zoom > 1) {
+ ALOGE("%s: Invalid zoom %f", __func__, zoom);
+ return Result::INVALID_ARGUMENTS;
+ }
return Stream::analyzeStatus("set_microphone_field_dimension",
mStream->set_microphone_field_dimension(mStream, zoom));
}
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 259473e..6c76d7b 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -641,7 +641,9 @@
/**
* Night mode
*
- * True indicates that night mode is currently enabled.
+ * True indicates that the night mode sensor has detected that the car cabin environment has
+ * low light. The platform could use this, for example, to enable appropriate UI for
+ * better viewing in dark or low light environments.
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ
@@ -983,6 +985,10 @@
*
* Indicates whether the vehicle is displaying temperature to the user as
* Celsius or Fahrenheit.
+ * VehiclePropConfig.configArray is used to indicate the supported temperature display units.
+ * For example: configArray[0] = CELSIUS
+ * configArray[1] = FAHRENHEIT
+ *
* This parameter MAY be used for displaying any HVAC temperature in the system.
* Values must be one of VehicleUnit::CELSIUS or VehicleUnit::FAHRENHEIT
* Note that internally, all temperatures are represented in floating point Celsius.
@@ -2794,6 +2800,14 @@
*/
int32_t areaId;
+ /**
+ * If the property has @data_enum, leave the range to zero.
+ *
+ * Range will be ignored in the following cases:
+ * - The VehiclePropertyType is not INT32, INT64 or FLOAT.
+ * - Both of min value and max value are zero.
+ */
+
int32_t minInt32Value;
int32_t maxInt32Value;
diff --git a/camera/common/1.0/default/Android.bp b/camera/common/1.0/default/Android.bp
index 21f81f5..3e5c6d7 100644
--- a/camera/common/1.0/default/Android.bp
+++ b/camera/common/1.0/default/Android.bp
@@ -20,6 +20,7 @@
"libhardware",
"libcamera_metadata",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"libexif",
],
include_dirs: ["system/media/private/camera/include"],
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index 21706a8..b8c40e9 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -25,7 +25,9 @@
namespace V1_0 {
namespace helper {
-using MapperError = android::hardware::graphics::mapper::V2_0::Error;
+using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
+using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
+using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
HandleImporter::HandleImporter() : mInitialized(false) {}
@@ -34,8 +36,14 @@
return;
}
- mMapper = IMapper::getService();
- if (mMapper == nullptr) {
+ mMapperV3 = IMapperV3::getService();
+ if (mMapperV3 != nullptr) {
+ mInitialized = true;
+ return;
+ }
+
+ mMapperV2 = IMapper::getService();
+ if (mMapperV2 == nullptr) {
ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
return;
}
@@ -45,10 +53,90 @@
}
void HandleImporter::cleanup() {
- mMapper.clear();
+ mMapperV3.clear();
+ mMapperV2.clear();
mInitialized = false;
}
+template<class M, class E>
+bool HandleImporter::importBufferInternal(const sp<M> mapper, buffer_handle_t& handle) {
+ E error;
+ buffer_handle_t importedHandle;
+ auto ret = mapper->importBuffer(
+ hidl_handle(handle),
+ [&](const auto& tmpError, const auto& tmpBufferHandle) {
+ error = tmpError;
+ importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
+ });
+
+ if (!ret.isOk()) {
+ ALOGE("%s: mapper importBuffer failed: %s",
+ __FUNCTION__, ret.description().c_str());
+ return false;
+ }
+
+ if (error != E::NONE) {
+ return false;
+ }
+
+ handle = importedHandle;
+ return true;
+}
+
+template<class M, class E>
+YCbCrLayout HandleImporter::lockYCbCrInternal(const sp<M> mapper, buffer_handle_t& buf,
+ uint64_t cpuUsage, const IMapper::Rect& accessRegion) {
+ hidl_handle acquireFenceHandle;
+ auto buffer = const_cast<native_handle_t*>(buf);
+ YCbCrLayout layout = {};
+
+ typename M::Rect accessRegionCopy = {accessRegion.left, accessRegion.top,
+ accessRegion.width, accessRegion.height};
+ mapper->lockYCbCr(buffer, cpuUsage, accessRegionCopy, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpLayout) {
+ if (tmpError == E::NONE) {
+ // Member by member copy from different versions of YCbCrLayout.
+ layout.y = tmpLayout.y;
+ layout.cb = tmpLayout.cb;
+ layout.cr = tmpLayout.cr;
+ layout.yStride = tmpLayout.yStride;
+ layout.cStride = tmpLayout.cStride;
+ layout.chromaStep = tmpLayout.chromaStep;
+ } else {
+ ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
+ }
+ });
+ return layout;
+}
+
+template<class M, class E>
+int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
+ int releaseFence = -1;
+ auto buffer = const_cast<native_handle_t*>(buf);
+
+ mapper->unlock(
+ buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+ if (tmpError == E::NONE) {
+ auto fenceHandle = tmpReleaseFence.getNativeHandle();
+ if (fenceHandle) {
+ if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
+ ALOGE("%s: bad release fence numInts %d numFds %d",
+ __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
+ return;
+ }
+ releaseFence = dup(fenceHandle->data[0]);
+ if (releaseFence < 0) {
+ ALOGE("%s: bad release fence FD %d",
+ __FUNCTION__, releaseFence);
+ }
+ }
+ } else {
+ ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
+ }
+ });
+ return releaseFence;
+}
+
// In IComposer, any buffer_handle_t is owned by the caller and we need to
// make a clone for hwcomposer2. We also need to translate empty handle
// to nullptr. This function does that, in-place.
@@ -63,33 +151,16 @@
initializeLocked();
}
- if (mMapper == nullptr) {
- ALOGE("%s: mMapper is null!", __FUNCTION__);
- return false;
+ if (mMapperV3 != nullptr) {
+ return importBufferInternal<IMapperV3, MapperErrorV3>(mMapperV3, handle);
}
- MapperError error;
- buffer_handle_t importedHandle;
- auto ret = mMapper->importBuffer(
- hidl_handle(handle),
- [&](const auto& tmpError, const auto& tmpBufferHandle) {
- error = tmpError;
- importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
- });
-
- if (!ret.isOk()) {
- ALOGE("%s: mapper importBuffer failed: %s",
- __FUNCTION__, ret.description().c_str());
- return false;
+ if (mMapperV2 != nullptr) {
+ return importBufferInternal<IMapper, MapperErrorV2>(mMapperV2, handle);
}
- if (error != MapperError::NONE) {
- return false;
- }
-
- handle = importedHandle;
-
- return true;
+ ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
+ return false;
}
void HandleImporter::freeBuffer(buffer_handle_t handle) {
@@ -98,15 +169,23 @@
}
Mutex::Autolock lock(mLock);
- if (mMapper == nullptr) {
- ALOGE("%s: mMapper is null!", __FUNCTION__);
+ if (mMapperV3 == nullptr && mMapperV2 == nullptr) {
+ ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
return;
}
- auto ret = mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
- if (!ret.isOk()) {
- ALOGE("%s: mapper freeBuffer failed: %s",
- __FUNCTION__, ret.description().c_str());
+ if (mMapperV3 != nullptr) {
+ auto ret = mMapperV3->freeBuffer(const_cast<native_handle_t*>(handle));
+ if (!ret.isOk()) {
+ ALOGE("%s: mapper freeBuffer failed: %s",
+ __FUNCTION__, ret.description().c_str());
+ }
+ } else {
+ auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
+ if (!ret.isOk()) {
+ ALOGE("%s: mapper freeBuffer failed: %s",
+ __FUNCTION__, ret.description().c_str());
+ }
}
}
@@ -138,91 +217,82 @@
buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
Mutex::Autolock lock(mLock);
void *ret = 0;
- IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
if (!mInitialized) {
initializeLocked();
}
- if (mMapper == nullptr) {
- ALOGE("%s: mMapper is null!", __FUNCTION__);
+ if (mMapperV3 == nullptr && mMapperV2 == nullptr) {
+ ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
return ret;
}
hidl_handle acquireFenceHandle;
auto buffer = const_cast<native_handle_t*>(buf);
- mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpPtr) {
- if (tmpError == MapperError::NONE) {
- ret = tmpPtr;
- } else {
- ALOGE("%s: failed to lock error %d!",
- __FUNCTION__, tmpError);
- }
- });
+ if (mMapperV3 != nullptr) {
+ IMapperV3::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
+ // No need to use bytesPerPixel and bytesPerStride because we are using
+ // an 1-D buffer and accressRegion.
+ mMapperV3->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
+ const auto& /*bytesPerStride*/) {
+ if (tmpError == MapperErrorV3::NONE) {
+ ret = tmpPtr;
+ } else {
+ ALOGE("%s: failed to lock error %d!",
+ __FUNCTION__, tmpError);
+ }
+ });
+ } else {
+ IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
+ mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpPtr) {
+ if (tmpError == MapperErrorV2::NONE) {
+ ret = tmpPtr;
+ } else {
+ ALOGE("%s: failed to lock error %d!",
+ __FUNCTION__, tmpError);
+ }
+ });
+ }
ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size);
return ret;
}
-
YCbCrLayout HandleImporter::lockYCbCr(
buffer_handle_t& buf, uint64_t cpuUsage,
const IMapper::Rect& accessRegion) {
Mutex::Autolock lock(mLock);
- YCbCrLayout layout = {};
if (!mInitialized) {
initializeLocked();
}
- if (mMapper == nullptr) {
- ALOGE("%s: mMapper is null!", __FUNCTION__);
- return layout;
+ if (mMapperV3 != nullptr) {
+ return lockYCbCrInternal<IMapperV3, MapperErrorV3>(
+ mMapperV3, buf, cpuUsage, accessRegion);
}
- hidl_handle acquireFenceHandle;
- auto buffer = const_cast<native_handle_t*>(buf);
- mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpLayout) {
- if (tmpError == MapperError::NONE) {
- layout = tmpLayout;
- } else {
- ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
- }
- });
+ if (mMapperV2 != nullptr) {
+ return lockYCbCrInternal<IMapper, MapperErrorV2>(
+ mMapperV2, buf, cpuUsage, accessRegion);
+ }
- ALOGV("%s: layout y %p cb %p cr %p y_str %d c_str %d c_step %d",
- __FUNCTION__, layout.y, layout.cb, layout.cr,
- layout.yStride, layout.cStride, layout.chromaStep);
- return layout;
+ ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
+ return {};
}
int HandleImporter::unlock(buffer_handle_t& buf) {
- int releaseFence = -1;
- auto buffer = const_cast<native_handle_t*>(buf);
- mMapper->unlock(
- buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
- if (tmpError == MapperError::NONE) {
- auto fenceHandle = tmpReleaseFence.getNativeHandle();
- if (fenceHandle) {
- if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
- ALOGE("%s: bad release fence numInts %d numFds %d",
- __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
- return;
- }
- releaseFence = dup(fenceHandle->data[0]);
- if (releaseFence <= 0) {
- ALOGE("%s: bad release fence FD %d",
- __FUNCTION__, releaseFence);
- }
- }
- } else {
- ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
- }
- });
+ if (mMapperV3 != nullptr) {
+ return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
+ }
+ if (mMapperV2 != nullptr) {
+ return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
+ }
- return releaseFence;
+ ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
+ return -1;
}
} // namespace helper
diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS
index 70128c7..f48a95c 100644
--- a/camera/common/1.0/default/OWNERS
+++ b/camera/common/1.0/default/OWNERS
@@ -1 +1 @@
-include platform/frameworks/av:camera/OWNERS
+include platform/frameworks/av:/camera/OWNERS
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
index f9cd9fb..a93d455 100644
--- a/camera/common/1.0/default/include/HandleImporter.h
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -19,6 +19,7 @@
#include <utils/Mutex.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
#include <cutils/native_handle.h>
using android::hardware::graphics::mapper::V2_0::IMapper;
@@ -57,10 +58,18 @@
void initializeLocked();
void cleanup();
+ template<class M, class E>
+ bool importBufferInternal(const sp<M> mapper, buffer_handle_t& handle);
+ template<class M, class E>
+ YCbCrLayout lockYCbCrInternal(const sp<M> mapper, buffer_handle_t& buf, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion);
+ template<class M, class E>
+ int unlockInternal(const sp<M> mapper, buffer_handle_t& buf);
+
Mutex mLock;
bool mInitialized;
- sp<IMapper> mMapper;
-
+ sp<IMapper> mMapperV2;
+ sp<graphics::mapper::V3_0::IMapper> mMapperV3;
};
} // namespace helper
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index 4a7fc9c..aa3b941 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -15,6 +15,7 @@
"android.hardware.camera.common@1.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.common@1.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp
index 325c008..edb008e 100644
--- a/camera/device/3.2/default/Android.bp
+++ b/camera/device/3.2/default/Android.bp
@@ -13,6 +13,7 @@
"android.hardware.camera.device@3.2",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"liblog",
"libhardware",
"libcamera_metadata",
diff --git a/camera/device/3.3/default/Android.bp b/camera/device/3.3/default/Android.bp
index b1e9b46..39d379d 100644
--- a/camera/device/3.3/default/Android.bp
+++ b/camera/device/3.3/default/Android.bp
@@ -15,6 +15,7 @@
"android.hardware.camera.device@3.3",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"liblog",
"libhardware",
"libcamera_metadata",
diff --git a/camera/device/3.4/default/Android.bp b/camera/device/3.4/default/Android.bp
index 272bf42..c22b13c 100644
--- a/camera/device/3.4/default/Android.bp
+++ b/camera/device/3.4/default/Android.bp
@@ -48,6 +48,7 @@
"android.hardware.camera.device@3.4",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"liblog",
"libhardware",
"libcamera_metadata",
@@ -84,6 +85,7 @@
"android.hardware.camera.device@3.4",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"liblog",
"libhardware",
"libcamera_metadata",
diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp
index 7a48865..26b3b67 100644
--- a/camera/device/3.5/default/Android.bp
+++ b/camera/device/3.5/default/Android.bp
@@ -49,6 +49,7 @@
"android.hardware.camera.device@3.5",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"liblog",
"libhardware",
"libcamera_metadata",
@@ -82,6 +83,7 @@
"android.hardware.camera.device@3.5",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"liblog",
"libhardware",
"libcamera_metadata",
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 9d73934..cb78fcb 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -12,6 +12,7 @@
"android.hardware.camera.device@3.5",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"camera.device@1.0-impl",
@@ -50,6 +51,7 @@
"android.hardware.camera.device@3.5",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"camera.device@3.3-impl",
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 5fb1fd8..2c3ed37 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -42,8 +42,10 @@
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"android.hidl.allocator@1.0",
"libgrallocusage",
"libhidlmemory",
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 33d23a0..200dd3f 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -54,8 +54,10 @@
#include <ui/GraphicBuffer.h>
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <android/hardware/graphics/mapper/2.0/types.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
@@ -6104,36 +6106,66 @@
sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
android::hardware::graphics::allocator::V2_0::IAllocator::getService();
- ASSERT_NE(nullptr, allocator.get());
+ sp<android::hardware::graphics::allocator::V3_0::IAllocator> allocatorV3 =
+ android::hardware::graphics::allocator::V3_0::IAllocator::getService();
+ sp<android::hardware::graphics::mapper::V3_0::IMapper> mapperV3 =
+ android::hardware::graphics::mapper::V3_0::IMapper::getService();
sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
android::hardware::graphics::mapper::V2_0::IMapper::getService();
- ASSERT_NE(mapper.get(), nullptr);
-
- android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo {};
- descriptorInfo.width = width;
- descriptorInfo.height = height;
- descriptorInfo.layerCount = 1;
- descriptorInfo.format = format;
- descriptorInfo.usage = usage;
-
::android::hardware::hidl_vec<uint32_t> descriptor;
- auto ret = mapper->createDescriptor(
- descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V2_0::Error err,
- ::android::hardware::hidl_vec<uint32_t> desc) {
- ASSERT_EQ(err, android::hardware::graphics::mapper::V2_0::Error::NONE);
- descriptor = desc;
- });
- ASSERT_TRUE(ret.isOk());
+ if (mapperV3 != nullptr && allocatorV3 != nullptr) {
+ android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo descriptorInfo {};
+ descriptorInfo.width = width;
+ descriptorInfo.height = height;
+ descriptorInfo.layerCount = 1;
+ descriptorInfo.format =
+ static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
+ descriptorInfo.usage = usage;
- ret = allocator->allocate(descriptor, 1u,
- [&](android::hardware::graphics::mapper::V2_0::Error err, uint32_t /*stride*/,
- const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) {
- ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE, err);
- ASSERT_EQ(buffers.size(), 1u);
- *buffer_handle = buffers[0];
- });
- ASSERT_TRUE(ret.isOk());
+ auto ret = mapperV3->createDescriptor(
+ descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V3_0::Error err,
+ ::android::hardware::hidl_vec<uint32_t> desc) {
+ ASSERT_EQ(err, android::hardware::graphics::mapper::V3_0::Error::NONE);
+ descriptor = desc;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ ret = allocatorV3->allocate(descriptor, 1u,
+ [&](android::hardware::graphics::mapper::V3_0::Error err, uint32_t /*stride*/,
+ const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) {
+ ASSERT_EQ(android::hardware::graphics::mapper::V3_0::Error::NONE, err);
+ ASSERT_EQ(buffers.size(), 1u);
+ *buffer_handle = buffers[0];
+ });
+ ASSERT_TRUE(ret.isOk());
+ } else {
+ ASSERT_NE(mapper.get(), nullptr);
+ ASSERT_NE(allocator.get(), nullptr);
+ android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo {};
+ descriptorInfo.width = width;
+ descriptorInfo.height = height;
+ descriptorInfo.layerCount = 1;
+ descriptorInfo.format = format;
+ descriptorInfo.usage = usage;
+
+ auto ret = mapper->createDescriptor(
+ descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V2_0::Error err,
+ ::android::hardware::hidl_vec<uint32_t> desc) {
+ ASSERT_EQ(err, android::hardware::graphics::mapper::V2_0::Error::NONE);
+ descriptor = desc;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ ret = allocator->allocate(descriptor, 1u,
+ [&](android::hardware::graphics::mapper::V2_0::Error err, uint32_t /*stride*/,
+ const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) {
+ ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE, err);
+ ASSERT_EQ(buffers.size(), 1u);
+ *buffer_handle = buffers[0];
+ });
+ ASSERT_TRUE(ret.isOk());
+ }
}
void CameraHidlTest::verifyRecommendedConfigs(const CameraMetadata& chars) {
diff --git a/current.txt b/current.txt
index d97c0b3..5742d66 100644
--- a/current.txt
+++ b/current.txt
@@ -410,7 +410,9 @@
ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types
1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
cd1757867a5e3a3faa362e785239515870d1a3c9ce756c6f0cf0f0fd8aac2547 android.hardware.radio@1.2::types
+722b3595548ed7f1953b6e0143dc842d4d6e290ff009a134eb518d7c17a09347 android.hardware.radio@1.2::types # b/112486807
e78cf871f9fd1c072874e481e06e18e2681763cf2aa38c1fd777d53bab4eb69b android.hardware.sensors@1.0::types
+c28859a334c1f540dea0a7d4f0baef0551ba76a3232f53c936196543ee35bc4d android.hardware.sensors@1.0::types # b/133264933
3d01e29e8129186f7567c4f9c8bee7480a0768e587b1be9b28adb0a6cbec6bf2 android.hardware.tv.cec@1.0::types
1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types
29c8da7a13c40d488f569c812441d5754ee45bdcdb8ce6564f524b708d10a057 android.hardware.vibrator@1.1::types
@@ -427,6 +429,7 @@
1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback
83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types
07d17800b298331e90d4ea5d8ba19a1ae3fe9c1dbff08d9f75fd3ade09496d67 android.hardware.audio.common@5.0::types
+b3c1ec989f317b9a36eac10f4e7b66aad2997302156899481553a67476e148dd android.hardware.audio.common@5.0::types # b/133453897
f269297866765b95ddd1825676cc8a772f0c7c9863286df596fc302781a42ff5 android.hardware.audio.effect@5.0::IAcousticEchoCancelerEffect
fa187b602d8939644ef708ed7627f2e3deac97899a4bda1de07f2ff126abe243 android.hardware.audio.effect@5.0::IAutomaticGainControlEffect
e1bf864ccb8458c0da1dcc74a2e748b1dca8ac360df590591cf82d98292d7981 android.hardware.audio.effect@5.0::IBassBoostEffect
@@ -526,6 +529,7 @@
a1c6b0761bcb89d6bf15a156f9306b8090b3a916a15fea1689b4b0c1738e382f android.hardware.radio@1.3::IRadio
e9d0f11a52715f5a29d89e2d8e2e21db1e16a43174af6b9d51a62d705cda1455 android.hardware.radio@1.3::IRadioIndication
d233f0da44f55fdef0a95db5229231412787bb67695cd1ea197ce89a3c2908b9 android.hardware.radio@1.3::IRadioResponse
+f5fbe4f28a9e346be36063eca4e6c864114a1a6fb64884db03fdd825791ad9b8 android.hardware.radio@1.3::IRadioResponse # b/132818184 for Android Q
750a363c8cec70baa1aac19e275c15233c5898e93c6bb5155fa2ca7f365490dc android.hardware.radio@1.3::types
ef4ab741f7e7762fb45e2e24ca83871f72006ce05f57aa9addc574893dd29872 android.hardware.radio@1.4::IRadio
33d9e6895cca98aa56296bb01720d18b8acd0e4de4960beb712e63ad147438a5 android.hardware.radio@1.4::IRadioIndication
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 2dceeb1..dffebd3 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -193,7 +193,8 @@
* the client (in seconds).
* Expected range for the input is
* [IncrementalResultsPeriodicityRange:MIN - IncrementalResultsPeriodicityRange:MAX]
- * This value must be less than or equal to maxSearchTime.
+ * This value must be less than or equal to maxSearchTime. If incremental results are
+ * not requested, implementations may ignore this value.
*/
int32_t incrementalResultsPeriodicity;
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index a3073ac..63d3187 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -228,7 +228,7 @@
.interval = 60,
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 600,
- .incrementalResults = false,
+ .incrementalResults = true,
.incrementalResultsPeriodicity = 0};
Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
@@ -260,7 +260,7 @@
.interval = 60,
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 600,
- .incrementalResults = false,
+ .incrementalResults = true,
.incrementalResultsPeriodicity = 11};
Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal
index c3bbe65..85085e2 100644
--- a/radio/1.3/IRadioResponse.hal
+++ b/radio/1.3/IRadioResponse.hal
@@ -44,6 +44,9 @@
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:MODEM_ERR
+ * RadioError:INVALID_STATE: this is for the case that the API is called in a single-sim
+ * mode, or when there is only one modem available, as this API should only
+ * be called in multi sim status.
*/
oneway enableModemResponse(RadioResponseInfo info);
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 5b7a06d..813dd13 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
@@ -35,7 +35,7 @@
toString(radioRsp_v1_3->rspInfo.error).c_str());
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
- RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED}));
+ RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
// checking if getModemStackStatus returns true, as modem was enabled above
if (RadioError::NONE == radioRsp_v1_3->rspInfo.error) {
@@ -52,7 +52,7 @@
toString(radioRsp_v1_3->rspInfo.error).c_str());
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
- RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED}));
+ RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
// verify that enableModem did set isEnabled correctly
EXPECT_EQ(true, radioRsp_v1_3->isModemEnabled);
}
diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp
index 2d0e089..6827132 100644
--- a/radio/1.4/vts/functional/Android.bp
+++ b/radio/1.4/vts/functional/Android.bp
@@ -31,7 +31,9 @@
"android.hardware.radio@1.2",
"android.hardware.radio@1.1",
"android.hardware.radio@1.0",
+ "android.hardware.radio.config@1.0",
+ "android.hardware.radio.config@1.1",
],
header_libs: ["radio.util.header@1.0"],
test_suites: ["general-tests"]
-}
\ No newline at end of file
+}
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 2093c25..696c746 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -119,6 +119,10 @@
network_type_bitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE;
+ // TODO(b/131634656): LTE_CA will be sent to modem as a RAF in Q, but LTE_CA is not a RAF,
+ // we will not send it to modem as a RAF in R.
+ network_type_bitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE_CA;
+
Return<void> res = radio_v1_4->setPreferredNetworkTypeBitmap(serial, network_type_bitmap);
ASSERT_OK(res);
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
index 4d80696..d2d21ce 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
@@ -47,6 +47,13 @@
EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+ sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig =
+ ::testing::VtsHalHidlTargetTestBase::getService<
+ ::android::hardware::radio::config::V1_1::IRadioConfig>();
+
+ /* Enforce Vts tesing with RadioConfig is existed. */
+ ASSERT_NE(nullptr, radioConfig.get());
+
/* Enforce Vts Testing with Sim Status Present only. */
EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.cardState);
}
@@ -84,4 +91,4 @@
serial = GetRandomSerialNumber();
radio_v1_4->getIccCardStatus(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
-}
\ No newline at end of file
+}
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 de7742c..f662472 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
@@ -22,6 +22,8 @@
#include <condition_variable>
#include <mutex>
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+
#include <android/hardware/radio/1.4/IRadio.h>
#include <android/hardware/radio/1.4/IRadioIndication.h>
#include <android/hardware/radio/1.4/IRadioResponse.h>
diff --git a/radio/config/1.0/vts/functional/radio_config_response.cpp b/radio/config/1.0/vts/functional/radio_config_response.cpp
index 97e8dca..a92db64 100644
--- a/radio/config/1.0/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.0/vts/functional/radio_config_response.cpp
@@ -21,11 +21,15 @@
RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
- const RadioResponseInfo& /* info */,
- const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+ rspInfo = info;
+ parent.notify();
return Void();
}
-Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent.notify();
return Void();
-}
\ No newline at end of file
+}
diff --git a/sensors/1.0/types.hal b/sensors/1.0/types.hal
index e91820c..cbbe92f 100644
--- a/sensors/1.0/types.hal
+++ b/sensors/1.0/types.hal
@@ -1008,10 +1008,40 @@
AINFO_VEC3_CALIBRATION,
/**
- * Location and orientation of sensor element in the device frame: origin is
- * the geometric center of the mobile device screen surface; the axis
- * definition corresponds to Android sensor definitions.
- * float[12]: 3x4 matrix in row major order
+ * Provides the orientation and location of the sensor element in terms of
+ * the Android coordinate system. This data is given as a 3x4 matrix
+ * consisting of a 3x3 rotation matrix (R) concatenated with a 3x1 location
+ * vector (t). The rotation matrix provides the orientation of the Android
+ * device coordinate frame relative to the local coordinate frame of the
+ * sensor. Note that assuming the axes conventions of the sensor are the
+ * same as Android, this is the inverse of the matrix applied to raw
+ * samples read from the sensor to convert them into the Android
+ * representation. The location vector represents the translation from the
+ * origin of the Android sensor coordinate system to the geometric center
+ * of the sensor, specified in millimeters (mm).
+ *
+ * float[12]: 3x4 matrix in row major order [R; t]
+ *
+ * Example:
+ * This raw buffer: {0, 1, 0, 0, -1, 0, 0, 10, 0, 0, 1, -2.5}
+ * Corresponds to this 3x4 matrix:
+ * 0 1 0 0
+ * -1 0 0 10
+ * 0 0 1 -2.5
+ * The sensor is oriented such that:
+ * - the device X axis corresponds to the sensor's local -Y axis
+ * - the device Y axis corresponds to the sensor's local X axis
+ * - the device Z axis and sensor's local Z axis are equivalent
+ * In other words, if viewing the origin of the Android coordinate
+ * system from the positive Z direction, the device coordinate frame is
+ * to be rotated 90 degrees counter-clockwise about the Z axis to align
+ * with the sensor's local coordinate frame. Equivalently, a vector in
+ * the Android coordinate frame may be multiplied with R to rotate it
+ * 90 degrees clockwise (270 degrees counter-clockwise), yielding its
+ * representation in the sensor's coordinate frame.
+ * Relative to the origin of the Android coordinate system, the physical
+ * center of the sensor is located 10mm in the positive Y direction, and
+ * 2.5mm in the negative Z direction.
*/
AINFO_SENSOR_PLACEMENT,
diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
index 85bcccd..64b4fb6 100644
--- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -91,12 +91,12 @@
};
/* Test code calls this function to wait for data/event callback */
+ /* Must set callbackType = INVALID before call this function */
inline std::cv_status wait(CallbackType waitForCallbackType) {
std::unique_lock<std::mutex> lock(mtx_);
EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a non-void-returning method
- callbackType = INVALID;
std::cv_status status = std::cv_status::no_timeout;
auto now = std::chrono::system_clock::now();
while (count_ == 0) {
@@ -469,6 +469,7 @@
*/
TEST_F(WifiNanIfaceHidlTest, getCapabilitiesRequest) {
uint16_t inputCmdId = 10;
+ callbackType = INVALID;
ASSERT_EQ(WifiStatusCode::SUCCESS,
HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code);
// wait for a callback
diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
index cc36fae..4dbc82b 100644
--- a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -100,13 +100,13 @@
};
/* Test code calls this function to wait for data/event callback */
+ /* Must set callbackType = INVALID before call this function */
inline std::cv_status wait(CallbackType waitForCallbackType) {
std::unique_lock<std::mutex> lock(mtx_);
EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a
// non-void-returning method
- callbackType = INVALID;
std::cv_status status = std::cv_status::no_timeout;
auto now = std::chrono::system_clock::now();
while (count_ == 0) {
@@ -475,6 +475,7 @@
*/
TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2InvalidArgs) {
uint16_t inputCmdId = 10;
+ callbackType = INVALID;
NanEnableRequest nanEnableRequest = {};
NanConfigRequestSupplemental nanConfigRequestSupp = {};
ASSERT_EQ(WifiStatusCode::SUCCESS,
@@ -509,6 +510,7 @@
*/
TEST_F(WifiNanIfaceHidlTest, configRequest_1_2InvalidArgs) {
uint16_t inputCmdId = 10;
+ callbackType = INVALID;
NanConfigRequest nanConfigRequest = {};
NanConfigRequestSupplemental nanConfigRequestSupp = {};
ASSERT_EQ(WifiStatusCode::SUCCESS,
diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk
index 199ea3b..1f91861 100644
--- a/wifi/1.3/default/Android.mk
+++ b/wifi/1.3/default/Android.mk
@@ -142,12 +142,14 @@
LOCAL_SRC_FILES := \
tests/hidl_struct_util_unit_tests.cpp \
tests/main.cpp \
+ tests/mock_interface_tool.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_ap_iface_unit_tests.cpp \
+ tests/wifi_nan_iface_unit_tests.cpp \
tests/wifi_chip_unit_tests.cpp \
tests/wifi_iface_util_unit_tests.cpp
LOCAL_STATIC_LIBRARIES := \
diff --git a/wifi/1.3/default/service.cpp b/wifi/1.3/default/service.cpp
index 73015cf..fcbc37c 100644
--- a/wifi/1.3/default/service.cpp
+++ b/wifi/1.3/default/service.cpp
@@ -48,12 +48,14 @@
configureRpcThreadpool(1, true /* callerWillJoin */);
+ const auto iface_tool =
+ std::make_shared<android::wifi_system::InterfaceTool>();
// Setup hwbinder service
android::sp<android::hardware::wifi::V1_3::IWifi> service =
new android::hardware::wifi::V1_3::implementation::Wifi(
- std::make_shared<WifiLegacyHal>(),
+ iface_tool, std::make_shared<WifiLegacyHal>(iface_tool),
std::make_shared<WifiModeController>(),
- std::make_shared<WifiIfaceUtil>(),
+ std::make_shared<WifiIfaceUtil>(iface_tool),
std::make_shared<WifiFeatureFlags>());
if (kLazyService) {
LazyServiceRegistrar registrar;
diff --git a/wifi/1.3/default/tests/mock_interface_tool.cpp b/wifi/1.3/default/tests/mock_interface_tool.cpp
new file mode 100644
index 0000000..b99a164
--- /dev/null
+++ b/wifi/1.3/default/tests/mock_interface_tool.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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_interface_tool.h"
+
+namespace android {
+namespace wifi_system {
+
+MockInterfaceTool::MockInterfaceTool() {}
+
+} // namespace wifi_system
+} // namespace android
diff --git a/wifi/1.3/default/tests/mock_interface_tool.h b/wifi/1.3/default/tests/mock_interface_tool.h
new file mode 100644
index 0000000..0f17551
--- /dev/null
+++ b/wifi/1.3/default/tests/mock_interface_tool.h
@@ -0,0 +1,44 @@
+/*
+ * 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_INTERFACE_TOOL_H
+#define MOCK_INTERFACE_TOOL_H
+
+#include <gmock/gmock.h>
+#include <wifi_system/interface_tool.h>
+
+namespace android {
+namespace wifi_system {
+
+class MockInterfaceTool : public InterfaceTool {
+ public:
+ MockInterfaceTool();
+
+ MOCK_METHOD1(GetUpState, bool(const char* if_name));
+ MOCK_METHOD2(SetUpState, bool(const char* if_name, bool request_up));
+ MOCK_METHOD1(SetWifiUpState, bool(bool request_up));
+ MOCK_METHOD2(SetMacAddress,
+ bool(const char* if_name,
+ const std::array<uint8_t, ETH_ALEN>& address));
+ MOCK_METHOD1(GetFactoryMacAddress,
+ std::array<uint8_t, ETH_ALEN>(const char* if_name));
+
+}; // class MockInterfaceTool
+
+} // namespace wifi_system
+} // namespace android
+
+#endif // MOCK_INTERFACE_TOOL_H
diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp
index 706cb6a..3d877c0 100644
--- a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp
+++ b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp
@@ -28,7 +28,9 @@
namespace implementation {
namespace iface_util {
-MockWifiIfaceUtil::MockWifiIfaceUtil() : WifiIfaceUtil() {}
+MockWifiIfaceUtil::MockWifiIfaceUtil(
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
+ : WifiIfaceUtil(iface_tool) {}
} // namespace iface_util
} // namespace implementation
} // namespace V1_3
diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.h b/wifi/1.3/default/tests/mock_wifi_iface_util.h
index 87ab5db..8ec93eb 100644
--- a/wifi/1.3/default/tests/mock_wifi_iface_util.h
+++ b/wifi/1.3/default/tests/mock_wifi_iface_util.h
@@ -30,12 +30,16 @@
class MockWifiIfaceUtil : public WifiIfaceUtil {
public:
- MockWifiIfaceUtil();
+ MockWifiIfaceUtil(
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
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>());
+ MOCK_METHOD2(registerIfaceEventHandlers,
+ void(const std::string&, IfaceEventHandlers));
+ MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
};
} // namespace iface_util
} // namespace implementation
diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
index 4cd279d..0a202c4 100644
--- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
+++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
@@ -28,7 +28,9 @@
namespace implementation {
namespace legacy_hal {
-MockWifiLegacyHal::MockWifiLegacyHal() : WifiLegacyHal() {}
+MockWifiLegacyHal::MockWifiLegacyHal(
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
+ : WifiLegacyHal(iface_tool) {}
} // namespace legacy_hal
} // namespace implementation
} // namespace V1_3
diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
index 53fa8d6..81cb1de 100644
--- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
+++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
@@ -30,7 +30,8 @@
class MockWifiLegacyHal : public WifiLegacyHal {
public:
- MockWifiLegacyHal();
+ MockWifiLegacyHal(
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
MOCK_METHOD0(initialize, wifi_error());
MOCK_METHOD0(start, wifi_error());
MOCK_METHOD2(stop, wifi_error(std::unique_lock<std::recursive_mutex>*,
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
index 28e028b..680f534 100644
--- a/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp
@@ -22,6 +22,7 @@
#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
#include "wifi_ap_iface.h"
+#include "mock_interface_tool.h"
#include "mock_wifi_feature_flags.h"
#include "mock_wifi_iface_util.h"
#include "mock_wifi_legacy_hal.h"
@@ -42,10 +43,12 @@
class WifiApIfaceTest : public Test {
protected:
+ std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+ new NiceMock<wifi_system::MockInterfaceTool>};
std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
- new NiceMock<legacy_hal::MockWifiLegacyHal>};
+ new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)};
std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
- new NiceMock<iface_util::MockWifiIfaceUtil>};
+ new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)};
std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
};
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 7928328..d8ce278 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -22,6 +22,7 @@
#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
#include "wifi_chip.h"
+#include "mock_interface_tool.h"
#include "mock_wifi_feature_flags.h"
#include "mock_wifi_iface_util.h"
#include "mock_wifi_legacy_hal.h"
@@ -263,12 +264,14 @@
sp<WifiChip> chip_;
ChipId chip_id_ = kFakeChipId;
+ std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+ new NiceMock<wifi_system::MockInterfaceTool>};
std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
- new NiceMock<legacy_hal::MockWifiLegacyHal>};
+ new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)};
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>};
+ new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)};
std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
@@ -700,6 +703,72 @@
});
}
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+ InvalidateAndRemoveNanOnStaRemove) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+
+ // Create NAN iface
+ ASSERT_EQ(createIface(IfaceType::NAN), "wlan0");
+
+ // We should have 1 nan iface.
+ chip_->getNanIfaceNames(
+ [](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+ ASSERT_EQ(iface_names.size(), 1u);
+ ASSERT_EQ(iface_names[0], "wlan0");
+ });
+ // Retrieve the exact iface object.
+ sp<IWifiNanIface> nan_iface;
+ chip_->getNanIface("wlan0", [&nan_iface](const WifiStatus& status,
+ const sp<IWifiNanIface>& iface) {
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+ ASSERT_NE(iface.get(), nullptr);
+ nan_iface = iface;
+ });
+
+ // Remove the STA iface.
+ removeIface(IfaceType::STA, "wlan0");
+ // We should have 0 nan iface now.
+ chip_->getNanIfaceNames(
+ [](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+ ASSERT_EQ(iface_names.size(), 0u);
+ });
+ // Any operation on the nan iface object should return error now.
+ nan_iface->getName(
+ [](const WifiStatus& status, const std::string& /* iface_name */) {
+ ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, status.code);
+ });
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+ InvalidateAndRemoveRttControllerOnStaRemove) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+
+ // Create RTT controller
+ sp<IWifiRttController> rtt_controller;
+ chip_->createRttController(
+ NULL, [&rtt_controller](const WifiStatus& status,
+ const sp<IWifiRttController>& rtt) {
+ if (WifiStatusCode::SUCCESS == status.code) {
+ ASSERT_NE(rtt.get(), nullptr);
+ rtt_controller = rtt;
+ }
+ });
+
+ // Remove the STA iface.
+ removeIface(IfaceType::STA, "wlan0");
+
+ // Any operation on the rtt controller object should return error now.
+ rtt_controller->getBoundIface(
+ [](const WifiStatus& status, const sp<IWifiIface>& /* iface */) {
+ ASSERT_EQ(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ status.code);
+ });
+}
+
////////// V1 Iface Combinations when AP creation is disabled //////////
class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
public:
@@ -732,6 +801,7 @@
ASSERT_TRUE(createIface(IfaceType::AP).empty());
}
+////////// Hypothetical Iface Combination with multiple ifaces //////////
class WifiChip_MultiIfaceTest : public WifiChipTest {
public:
void SetUp() override {
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
index e5758fa..28d23ff 100644
--- a/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp
@@ -21,10 +21,15 @@
#undef NAN
#include "wifi_iface_util.h"
+#include "mock_interface_tool.h"
+
+using testing::NiceMock;
using testing::Test;
namespace {
constexpr uint8_t kValidUnicastLocallyAssignedMacAddressMask = 0x02;
+constexpr uint8_t kMacAddress[] = {0x02, 0x12, 0x45, 0x56, 0xab, 0xcc};
+constexpr char kIfaceName[] = "test-wlan0";
bool isValidUnicastLocallyAssignedMacAddress(
const std::array<uint8_t, 6>& mac_address) {
@@ -38,19 +43,52 @@
namespace wifi {
namespace V1_3 {
namespace implementation {
+namespace iface_util {
class WifiIfaceUtilTest : public Test {
protected:
- iface_util::WifiIfaceUtil iface_util_;
+ std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+ new NiceMock<wifi_system::MockInterfaceTool>};
+ WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_);
};
TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) {
- auto mac_address = iface_util_.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());
+ ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress());
+ ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress());
}
+
+TEST_F(WifiIfaceUtilTest, IfaceEventHandlers_SetMacAddress) {
+ std::array<uint8_t, 6> mac_address = {};
+ std::copy(std::begin(kMacAddress), std::end(kMacAddress),
+ std::begin(mac_address));
+ EXPECT_CALL(*iface_tool_, SetMacAddress(testing::_, testing::_))
+ .WillRepeatedly(testing::Return(true));
+ EXPECT_CALL(*iface_tool_, SetUpState(testing::_, testing::_))
+ .WillRepeatedly(testing::Return(true));
+
+ // Register for iface state toggle events.
+ bool callback_invoked = false;
+ iface_util::IfaceEventHandlers event_handlers = {};
+ event_handlers.on_state_toggle_off_on =
+ [&callback_invoked](const std::string& /* iface_name */) {
+ callback_invoked = true;
+ };
+ iface_util_->registerIfaceEventHandlers(kIfaceName, event_handlers);
+ // Invoke setMacAddress and ensure that the cb is invoked.
+ ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
+ ASSERT_TRUE(callback_invoked);
+
+ // Unregister for iface state toggle events.
+ callback_invoked = false;
+ iface_util_->unregisterIfaceEventHandlers(kIfaceName);
+ // Invoke setMacAddress and ensure that the cb is not invoked.
+ ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
+ ASSERT_FALSE(callback_invoked);
+}
+} // namespace iface_util
} // namespace implementation
} // namespace V1_3
} // namespace wifi
diff --git a/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp
new file mode 100644
index 0000000..eb6c610
--- /dev/null
+++ b/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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_nan_iface.h"
+
+#include "mock_interface_tool.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 {
+
+bool CaptureIfaceEventHandlers(
+ const std::string& /* iface_name*/,
+ iface_util::IfaceEventHandlers in_iface_event_handlers,
+ iface_util::IfaceEventHandlers* out_iface_event_handlers) {
+ *out_iface_event_handlers = in_iface_event_handlers;
+ return true;
+}
+
+class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback {
+ public:
+ MockNanIfaceEventCallback() = default;
+
+ MOCK_METHOD3(notifyCapabilitiesResponse,
+ Return<void>(uint16_t, const WifiNanStatus&,
+ const NanCapabilities&));
+ MOCK_METHOD2(notifyEnableResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD2(notifyConfigResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD2(notifyDisableResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD3(notifyStartPublishResponse,
+ Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
+ MOCK_METHOD2(notifyStopPublishResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD3(notifyStartSubscribeResponse,
+ Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
+ MOCK_METHOD2(notifyStopSubscribeResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD2(notifyTransmitFollowupResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD2(notifyCreateDataInterfaceResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD2(notifyDeleteDataInterfaceResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD3(notifyInitiateDataPathResponse,
+ Return<void>(uint16_t, const WifiNanStatus&, uint32_t));
+ MOCK_METHOD2(notifyRespondToDataPathIndicationResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD2(notifyTerminateDataPathResponse,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD1(eventClusterEvent, Return<void>(const NanClusterEventInd&));
+ MOCK_METHOD1(eventDisabled, Return<void>(const WifiNanStatus&));
+ MOCK_METHOD2(eventPublishTerminated,
+ Return<void>(uint8_t, const WifiNanStatus&));
+ MOCK_METHOD2(eventSubscribeTerminated,
+ Return<void>(uint8_t, const WifiNanStatus&));
+ MOCK_METHOD1(eventMatch, Return<void>(const NanMatchInd&));
+ MOCK_METHOD2(eventMatchExpired, Return<void>(uint8_t, uint32_t));
+ MOCK_METHOD1(eventFollowupReceived,
+ Return<void>(const NanFollowupReceivedInd&));
+ MOCK_METHOD2(eventTransmitFollowup,
+ Return<void>(uint16_t, const WifiNanStatus&));
+ MOCK_METHOD1(eventDataPathRequest,
+ Return<void>(const NanDataPathRequestInd&));
+ MOCK_METHOD1(eventDataPathConfirm,
+ Return<void>(const NanDataPathConfirmInd&));
+ MOCK_METHOD1(eventDataPathTerminated, Return<void>(uint32_t));
+};
+
+class WifiNanIfaceTest : public Test {
+ protected:
+ std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+ new NiceMock<wifi_system::MockInterfaceTool>};
+ std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+ new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)};
+ std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+ new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)};
+};
+
+TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) {
+ iface_util::IfaceEventHandlers captured_iface_event_handlers = {};
+ EXPECT_CALL(*legacy_hal_,
+ nanRegisterCallbackHandlers(testing::_, testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ EXPECT_CALL(*iface_util_,
+ registerIfaceEventHandlers(testing::_, testing::_))
+ .WillOnce(testing::Invoke(
+ bind(CaptureIfaceEventHandlers, std::placeholders::_1,
+ std::placeholders::_2, &captured_iface_event_handlers)));
+ sp<WifiNanIface> nan_iface =
+ new WifiNanIface(kIfaceName, legacy_hal_, iface_util_);
+
+ // Register a mock nan event callback.
+ sp<NiceMock<MockNanIfaceEventCallback>> mock_event_callback{
+ new NiceMock<MockNanIfaceEventCallback>};
+ nan_iface->registerEventCallback(
+ mock_event_callback, [](const WifiStatus& status) {
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+ });
+ // Ensure that the eventDisabled() function in mock callback will be
+ // invoked.
+ WifiNanStatus expected_nan_status = {
+ NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
+ EXPECT_CALL(*mock_event_callback, eventDisabled(expected_nan_status))
+ .Times(1);
+
+ // Trigger the iface state toggle callback.
+ captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName);
+}
+} // 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 1f64085..2f21819 100644
--- a/wifi/1.3/default/wifi.cpp
+++ b/wifi/1.3/default/wifi.cpp
@@ -34,11 +34,13 @@
using hidl_return_util::validateAndCallWithLock;
Wifi::Wifi(
+ const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
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),
+ : iface_tool_(iface_tool),
+ legacy_hal_(legacy_hal),
mode_controller_(mode_controller),
iface_util_(iface_util),
feature_flags_(feature_flags),
diff --git a/wifi/1.3/default/wifi.h b/wifi/1.3/default/wifi.h
index c4ab773..1c2a154 100644
--- a/wifi/1.3/default/wifi.h
+++ b/wifi/1.3/default/wifi.h
@@ -40,7 +40,8 @@
*/
class Wifi : public V1_3::IWifi {
public:
- Wifi(const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
+ 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,
@@ -77,6 +78,7 @@
// Instance is created in this root level |IWifi| HIDL interface object
// and shared with all the child HIDL interface objects.
+ std::shared_ptr<wifi_system::InterfaceTool> iface_tool_;
std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_;
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index b768959..e9991dc 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -634,6 +634,27 @@
rtt_controllers_.clear();
}
+void WifiChip::invalidateAndRemoveDependencies(
+ const std::string& removed_iface_name) {
+ for (const auto& nan_iface : nan_ifaces_) {
+ if (nan_iface->getName() == removed_iface_name) {
+ invalidateAndClear(nan_ifaces_, nan_iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback
+ ->onIfaceRemoved(IfaceType::NAN, removed_iface_name)
+ .isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+ }
+ }
+ }
+ }
+ for (const auto& rtt : rtt_controllers_) {
+ if (rtt->getIfaceName() == removed_iface_name) {
+ invalidateAndClear(rtt_controllers_, rtt);
+ }
+ }
+}
+
std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {
return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_};
}
@@ -819,6 +840,11 @@
if (!iface.get()) {
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
}
+ // Invalidate & remove any dependent objects first.
+ // Note: This is probably not required because we never create
+ // nan/rtt objects over AP iface. But, there is no harm to do it
+ // here and not make that assumption all over the place.
+ invalidateAndRemoveDependencies(ifname);
invalidateAndClear(ap_ifaces_, iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
@@ -835,7 +861,7 @@
}
// These are still assumed to be based on wlan0.
std::string ifname = getFirstActiveWlanIfaceName();
- sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
+ sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_, iface_util_);
nan_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
@@ -960,6 +986,8 @@
if (!iface.get()) {
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
}
+ // Invalidate & remove any dependent objects first.
+ invalidateAndRemoveDependencies(ifname);
invalidateAndClear(sta_ifaces_, iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
@@ -1435,6 +1463,13 @@
return canCurrentModeSupportIfaceCombo(req_iface_combo);
}
+bool WifiChip::isDualApAllowedInCurrentMode() {
+ // Check if we can support atleast 1 STA & 1 AP concurrently.
+ std::map<IfaceType, size_t> req_iface_combo;
+ req_iface_combo[IfaceType::AP] = 2;
+ return canCurrentModeSupportIfaceCombo(req_iface_combo);
+}
+
std::string WifiChip::getFirstActiveWlanIfaceName() {
if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName();
if (ap_ifaces_.size() > 0) return ap_ifaces_[0]->getName();
@@ -1460,10 +1495,12 @@
}
// AP iface names start with idx 1 for modes supporting
-// concurrent STA, else start with idx 0.
+// concurrent STA and not dual AP, else start with idx 0.
std::string WifiChip::allocateApIfaceName() {
- return allocateApOrStaIfaceName(
- isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
+ return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() &&
+ !isDualApAllowedInCurrentMode())
+ ? 1
+ : 0);
}
// STA iface names start with idx 0.
diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h
index 3d12f4c..153ca6a 100644
--- a/wifi/1.3/default/wifi_chip.h
+++ b/wifi/1.3/default/wifi_chip.h
@@ -155,6 +155,9 @@
private:
void invalidateAndRemoveAllIfaces();
+ // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are
+ // invalidated & removed.
+ void invalidateAndRemoveDependencies(const std::string& removed_iface_name);
// Corresponding worker functions for the HIDL methods.
std::pair<WifiStatus, ChipId> getIdInternal();
@@ -237,6 +240,7 @@
bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
bool isValidModeId(ChipModeId mode_id);
bool isStaApConcurrencyAllowedInCurrentMode();
+ bool isDualApAllowedInCurrentMode();
std::string getFirstActiveWlanIfaceName();
std::string allocateApOrStaIfaceName(uint32_t start_idx);
std::string allocateApIfaceName();
diff --git a/wifi/1.3/default/wifi_iface_util.cpp b/wifi/1.3/default/wifi_iface_util.cpp
index 5d61271..34bc02d 100644
--- a/wifi/1.3/default/wifi_iface_util.cpp
+++ b/wifi/1.3/default/wifi_iface_util.cpp
@@ -39,27 +39,39 @@
namespace implementation {
namespace iface_util {
-WifiIfaceUtil::WifiIfaceUtil() : random_mac_address_(nullptr) {}
+WifiIfaceUtil::WifiIfaceUtil(
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
+ : iface_tool_(iface_tool),
+ random_mac_address_(nullptr),
+ event_handlers_map_() {}
std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(
const std::string& iface_name) {
- return iface_tool_.GetFactoryMacAddress(iface_name.c_str());
+ return iface_tool_.lock()->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)) {
+ if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
LOG(ERROR) << "SetUpState(false) failed.";
return false;
}
- if (!iface_tool_.SetMacAddress(iface_name.c_str(), mac)) {
+ if (!iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac)) {
LOG(ERROR) << "SetMacAddress failed.";
return false;
}
- if (!iface_tool_.SetUpState(iface_name.c_str(), true)) {
+ if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
LOG(ERROR) << "SetUpState(true) failed.";
return false;
}
+ IfaceEventHandlers event_handlers = {};
+ const auto it = event_handlers_map_.find(iface_name);
+ if (it != event_handlers_map_.end()) {
+ event_handlers = it->second;
+ }
+ if (event_handlers.on_state_toggle_off_on != nullptr) {
+ event_handlers.on_state_toggle_off_on(iface_name);
+ }
LOG(DEBUG) << "Successfully SetMacAddress.";
return true;
}
@@ -73,6 +85,16 @@
return *random_mac_address_.get();
}
+void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name,
+ IfaceEventHandlers handlers) {
+ event_handlers_map_[iface_name] = handlers;
+}
+
+void WifiIfaceUtil::unregisterIfaceEventHandlers(
+ const std::string& iface_name) {
+ event_handlers_map_.erase(iface_name);
+}
+
std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() {
std::array<uint8_t, 6> address = {};
std::random_device rd;
diff --git a/wifi/1.3/default/wifi_iface_util.h b/wifi/1.3/default/wifi_iface_util.h
index b238234..98073e0 100644
--- a/wifi/1.3/default/wifi_iface_util.h
+++ b/wifi/1.3/default/wifi_iface_util.h
@@ -28,12 +28,19 @@
namespace implementation {
namespace iface_util {
+// Iface event handlers.
+struct IfaceEventHandlers {
+ // Callback to be invoked when the iface is set down & up for MAC address
+ // change.
+ std::function<void(const std::string& iface_name)> on_state_toggle_off_on;
+};
+
/**
* Util class for common iface operations.
*/
class WifiIfaceUtil {
public:
- WifiIfaceUtil();
+ WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
virtual ~WifiIfaceUtil() = default;
virtual std::array<uint8_t, 6> getFactoryMacAddress(
@@ -45,11 +52,17 @@
// daemon. (So, changes on every reboot)
virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress();
+ // Register for any iface event callbacks for the provided interface.
+ virtual void registerIfaceEventHandlers(const std::string& iface_name,
+ IfaceEventHandlers handlers);
+ virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
+
private:
std::array<uint8_t, 6> createRandomMacAddress();
- wifi_system::InterfaceTool iface_tool_;
+ std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
+ std::map<std::string, IfaceEventHandlers> event_handlers_map_;
};
} // namespace iface_util
diff --git a/wifi/1.3/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp
index 7f9b635..485bd16 100644
--- a/wifi/1.3/default/wifi_legacy_hal.cpp
+++ b/wifi/1.3/default/wifi_legacy_hal.cpp
@@ -333,10 +333,12 @@
}
// End of the free-standing "C" style callbacks.
-WifiLegacyHal::WifiLegacyHal()
+WifiLegacyHal::WifiLegacyHal(
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
: global_handle_(nullptr),
awaiting_event_loop_termination_(false),
- is_started_(false) {}
+ is_started_(false),
+ iface_tool_(iface_tool) {}
wifi_error WifiLegacyHal::initialize() {
LOG(DEBUG) << "Initialize legacy HAL";
@@ -371,7 +373,7 @@
property_set(kDriverPropName, "ok");
LOG(DEBUG) << "Starting legacy HAL";
- if (!iface_tool_.SetWifiUpState(true)) {
+ if (!iface_tool_.lock()->SetWifiUpState(true)) {
LOG(ERROR) << "Failed to set WiFi interface up";
return WIFI_ERROR_UNKNOWN;
}
@@ -407,7 +409,7 @@
// Invalidate all the internal pointers now that the HAL is
// stopped.
invalidate();
- iface_tool_.SetWifiUpState(false);
+ iface_tool_.lock()->SetWifiUpState(false);
on_stop_complete_user_callback();
is_started_ = false;
};
diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h
index a3ed460..9cfa172 100644
--- a/wifi/1.3/default/wifi_legacy_hal.h
+++ b/wifi/1.3/default/wifi_legacy_hal.h
@@ -170,7 +170,7 @@
*/
class WifiLegacyHal {
public:
- WifiLegacyHal();
+ WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
virtual ~WifiLegacyHal() = default;
// Initialize the legacy HAL function table.
@@ -391,7 +391,7 @@
std::condition_variable_any stop_wait_cv_;
// Flag to indicate if the legacy HAL has been started.
bool is_started_;
- wifi_system::InterfaceTool iface_tool_;
+ std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
};
} // namespace legacy_hal
diff --git a/wifi/1.3/default/wifi_nan_iface.cpp b/wifi/1.3/default/wifi_nan_iface.cpp
index 4325f44..ff9f422 100644
--- a/wifi/1.3/default/wifi_nan_iface.cpp
+++ b/wifi/1.3/default/wifi_nan_iface.cpp
@@ -30,8 +30,12 @@
WifiNanIface::WifiNanIface(
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) {
// Register all the callbacks here. these should be valid for the lifetime
// of the object. Whenever the mode changes legacy HAL will remove
// all of these callbacks.
@@ -498,6 +502,26 @@
LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
invalidate();
}
+
+ // Register for iface state toggle events.
+ iface_util::IfaceEventHandlers event_handlers = {};
+ event_handlers.on_state_toggle_off_on =
+ [weak_ptr_this](const std::string& /* iface_name */) {
+ const auto shared_ptr_this = weak_ptr_this.promote();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ // Tell framework that NAN has been disabled.
+ WifiNanStatus status = {
+ NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventDisabled(status).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+ iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers);
}
void WifiNanIface::invalidate() {
@@ -505,7 +529,7 @@
legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1");
-
+ iface_util_.lock()->unregisterIfaceEventHandlers(ifname_);
legacy_hal_.reset();
event_cb_handler_.invalidate();
event_cb_handler_1_2_.invalidate();
diff --git a/wifi/1.3/default/wifi_nan_iface.h b/wifi/1.3/default/wifi_nan_iface.h
index f735d61..737be93 100644
--- a/wifi/1.3/default/wifi_nan_iface.h
+++ b/wifi/1.3/default/wifi_nan_iface.h
@@ -22,6 +22,7 @@
#include <android/hardware/wifi/1.2/IWifiNanIface.h>
#include "hidl_callback_util.h"
+#include "wifi_iface_util.h"
#include "wifi_legacy_hal.h"
namespace android {
@@ -37,7 +38,8 @@
class WifiNanIface : public V1_2::IWifiNanIface {
public:
WifiNanIface(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();
@@ -147,6 +149,7 @@
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<V1_0::IWifiNanIfaceEventCallback>
event_cb_handler_;
diff --git a/wifi/1.3/default/wifi_rtt_controller.cpp b/wifi/1.3/default/wifi_rtt_controller.cpp
index fa317e3..3dcbee6 100644
--- a/wifi/1.3/default/wifi_rtt_controller.cpp
+++ b/wifi/1.3/default/wifi_rtt_controller.cpp
@@ -49,6 +49,8 @@
return event_callbacks_;
}
+std::string WifiRttController::getIfaceName() { return ifname_; }
+
Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
return validateAndCall(
this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
diff --git a/wifi/1.3/default/wifi_rtt_controller.h b/wifi/1.3/default/wifi_rtt_controller.h
index 9798b79..eedd22a 100644
--- a/wifi/1.3/default/wifi_rtt_controller.h
+++ b/wifi/1.3/default/wifi_rtt_controller.h
@@ -42,6 +42,7 @@
void invalidate();
bool isValid();
std::vector<sp<IWifiRttControllerEventCallback>> getEventCallbacks();
+ std::string getIfaceName();
// HIDL methods exposed.
Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;