Merge "Fix doc on getModemStackStatus"
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);
 };