Merge "Bring multi-channel transport into the glorious new age"
diff --git a/tests/Android.bp b/tests/Android.bp
index 41043d9..9bb4bf5 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -15,6 +15,7 @@
     "memory/1.0",
     "memory/1.0/default",
     "msgq/1.0",
+    "msgq/1.0/default",
     "pointer/1.0",
     "pointer/1.0/default",
     "pointer/1.0/default/lib",
diff --git a/tests/msgq/1.0/default/Android.bp b/tests/msgq/1.0/default/Android.bp
new file mode 100644
index 0000000..b53fcd3
--- /dev/null
+++ b/tests/msgq/1.0/default/Android.bp
@@ -0,0 +1,19 @@
+cc_library_shared {
+    name: "android.hardware.tests.msgq@1.0-impl",
+    relative_install_path: "hw",
+    proprietary: true,
+    srcs: [
+        "TestMsgQ.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libfmq",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.tests.msgq@1.0",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/tests/msgq/1.0/default/TestMsgQ.cpp b/tests/msgq/1.0/default/TestMsgQ.cpp
new file mode 100644
index 0000000..7cc4f5b
--- /dev/null
+++ b/tests/msgq/1.0/default/TestMsgQ.cpp
@@ -0,0 +1,135 @@
+#include "TestMsgQ.h"
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace msgq {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::tests::msgq::V1_0::ITestMsgQ follow.
+Return<void> TestMsgQ::configureFmqSyncReadWrite(configureFmqSyncReadWrite_cb _hidl_cb) {
+    static constexpr size_t kNumElementsInQueue = 1024;
+    mFmqSynchronized.reset(new (std::nothrow) MessageQueueSync(
+            kNumElementsInQueue, true /* configureEventFlagWord */));
+    if ((mFmqSynchronized == nullptr) || (mFmqSynchronized->isValid() == false)) {
+        _hidl_cb(false /* ret */, MessageQueueSync::Descriptor());
+    } else {
+        /*
+         * Initialize the EventFlag word with bit FMQ_NOT_FULL.
+         */
+        auto evFlagWordPtr = mFmqSynchronized->getEventFlagWord();
+        if (evFlagWordPtr != nullptr) {
+            std::atomic_init(evFlagWordPtr,
+                             static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL));
+        }
+        _hidl_cb(true /* ret */, *mFmqSynchronized->getDesc());
+    }
+    return Void();
+}
+
+Return<void> TestMsgQ::getFmqUnsyncWrite(bool configureFmq, getFmqUnsyncWrite_cb _hidl_cb) {
+    if (configureFmq) {
+        static constexpr size_t kNumElementsInQueue = 1024;
+        mFmqUnsynchronized.reset(new (std::nothrow) MessageQueueUnsync(kNumElementsInQueue));
+    }
+    if ((mFmqUnsynchronized == nullptr) ||
+        (mFmqUnsynchronized->isValid() == false)) {
+        _hidl_cb(false /* ret */, MessageQueueUnsync::Descriptor());
+    } else {
+        _hidl_cb(true /* ret */, *mFmqUnsynchronized->getDesc());
+    }
+    return Void();
+}
+
+Return<bool> TestMsgQ::requestWriteFmqSync(int32_t count) {
+    std::vector<uint16_t> data(count);
+    for (int i = 0; i < count; i++) {
+        data[i] = i;
+    }
+    bool result = mFmqSynchronized->write(&data[0], count);
+    return result;
+}
+
+Return<bool> TestMsgQ::requestReadFmqSync(int32_t count) {
+    std::vector<uint16_t> data(count);
+    bool result = mFmqSynchronized->read(&data[0], count)
+            && verifyData(&data[0], count);
+    return result;
+}
+
+Return<bool> TestMsgQ::requestWriteFmqUnsync(int32_t count) {
+    std::vector<uint16_t> data(count);
+    for (int i = 0; i < count; i++) {
+        data[i] = i;
+    }
+    bool result = mFmqUnsynchronized->write(&data[0], count);
+    return result;
+}
+
+Return<bool> TestMsgQ::requestReadFmqUnsync(int32_t count) {
+    std::vector<uint16_t> data(count);
+    bool result =
+            mFmqUnsynchronized->read(&data[0], count) && verifyData(&data[0], count);
+    return result;
+}
+
+Return<void> TestMsgQ::requestBlockingRead(int32_t count) {
+    std::vector<uint16_t> data(count);
+    bool result = mFmqSynchronized->readBlocking(
+            &data[0],
+            count,
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+            5000000000 /* timeOutNanos */);
+
+    if (result == false) {
+        ALOGE("Blocking read fails");
+    }
+    return Void();
+}
+
+Return<void> TestMsgQ::requestBlockingReadDefaultEventFlagBits(int32_t count) {
+    std::vector<uint16_t> data(count);
+    bool result = mFmqSynchronized->readBlocking(
+            &data[0],
+            count);
+
+    if (result == false) {
+        ALOGE("Blocking read fails");
+    }
+
+    return Void();
+}
+
+Return<void> TestMsgQ::requestBlockingReadRepeat(int32_t count, int32_t numIter) {
+    std::vector<uint16_t> data(count);
+    for (int i = 0; i < numIter; i++) {
+        bool result = mFmqSynchronized->readBlocking(
+                &data[0],
+                count,
+                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+                5000000000 /* timeOutNanos */);
+
+        if (result == false) {
+            ALOGE("Blocking read fails");
+            break;
+        }
+    }
+    return Void();
+}
+
+
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+
+ITestMsgQ* HIDL_FETCH_ITestMsgQ(const char* /* name */) {
+    return new TestMsgQ();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace msgq
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
diff --git a/tests/msgq/1.0/default/TestMsgQ.h b/tests/msgq/1.0/default/TestMsgQ.h
new file mode 100644
index 0000000..760d931
--- /dev/null
+++ b/tests/msgq/1.0/default/TestMsgQ.h
@@ -0,0 +1,77 @@
+#ifndef ANDROID_HARDWARE_TESTS_MSGQ_V1_0_TESTMSGQ_H
+#define ANDROID_HARDWARE_TESTS_MSGQ_V1_0_TESTMSGQ_H
+
+#include <android/hardware/tests/msgq/1.0/ITestMsgQ.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <fmq/MessageQueue.h>
+#include <fmq/EventFlag.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace msgq {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tests::msgq::V1_0::ITestMsgQ;
+using ::android::hidl::base::V1_0::DebugInfo;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::kUnsynchronizedWrite;
+using android::hardware::MQDescriptorSync;
+using android::hardware::MQDescriptorUnsync;
+
+using android::hardware::MessageQueue;
+
+struct TestMsgQ : public ITestMsgQ {
+    typedef MessageQueue<uint16_t, kSynchronizedReadWrite> MessageQueueSync;
+    typedef MessageQueue<uint16_t, kUnsynchronizedWrite> MessageQueueUnsync;
+
+    TestMsgQ() : mFmqSynchronized(nullptr), mFmqUnsynchronized(nullptr) {}
+
+    // Methods from ::android::hardware::tests::msgq::V1_0::ITestMsgQ follow.
+    Return<void> configureFmqSyncReadWrite(configureFmqSyncReadWrite_cb _hidl_cb) override;
+    Return<void> getFmqUnsyncWrite(bool configureFmq, getFmqUnsyncWrite_cb _hidl_cb) override;
+    Return<bool> requestWriteFmqSync(int32_t count) override;
+    Return<bool> requestReadFmqSync(int32_t count) override;
+    Return<bool> requestWriteFmqUnsync(int32_t count) override;
+    Return<bool> requestReadFmqUnsync(int32_t count) override;
+    Return<void> requestBlockingRead(int32_t count) override;
+    Return<void> requestBlockingReadDefaultEventFlagBits(int32_t count) override;
+    Return<void> requestBlockingReadRepeat(int32_t count, int32_t numIter) override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+private:
+    std::unique_ptr<MessageQueueSync> mFmqSynchronized;
+    std::unique_ptr<MessageQueueUnsync> mFmqUnsynchronized;
+
+    /*
+     * Utility function to verify data read from the fast message queue.
+     */
+    bool verifyData(uint16_t* data, int count) {
+        for (int i = 0; i < count; i++) {
+            if (data[i] != i) return false;
+        }
+        return true;
+    }
+};
+
+extern "C" ITestMsgQ* HIDL_FETCH_ITestMsgQ(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace msgq
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TESTS_MSGQ_V1_0_TESTMSGQ_H
diff --git a/wifi/1.0/default/hidl_struct_util.cpp b/wifi/1.0/default/hidl_struct_util.cpp
index 485ae7e..5917efc 100644
--- a/wifi/1.0/default/hidl_struct_util.cpp
+++ b/wifi/1.0/default/hidl_struct_util.cpp
@@ -354,7 +354,10 @@
         hidl_scan_params.buckets[bucket_idx];
     legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec =
         legacy_scan_params->buckets[bucket_idx];
-    legacy_bucket_spec.bucket = bucket_idx;
+    if (hidl_bucket_spec.bucketIdx >= MAX_BUCKETS) {
+      return false;
+    }
+    legacy_bucket_spec.bucket = hidl_bucket_spec.bucketIdx;
     legacy_bucket_spec.band =
         convertHidlWifiBandToLegacy(hidl_bucket_spec.band);
     legacy_bucket_spec.period = hidl_bucket_spec.periodInMs;
diff --git a/wifi/1.0/default/wifi.cpp b/wifi/1.0/default/wifi.cpp
index 3d482b4..b48844e 100644
--- a/wifi/1.0/default/wifi.cpp
+++ b/wifi/1.0/default/wifi.cpp
@@ -115,6 +115,7 @@
       }
     }
   }
+  LOG(INFO) << "Wifi HAL started";
   return wifi_status;
 }
 
@@ -139,6 +140,13 @@
       }
     }
   }
+  // Clear the chip object and its child objects since the HAL is now
+  // stopped.
+  if (chip_.get()) {
+    chip_->invalidate();
+    chip_.clear();
+  }
+  LOG(INFO) << "Wifi HAL stopped";
   return wifi_status;
 }
 
@@ -172,13 +180,7 @@
 
 WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() {
   run_state_ = RunState::STOPPING;
-  const auto on_complete_callback_ = [&]() {
-    if (chip_.get()) {
-      chip_->invalidate();
-    }
-    chip_.clear();
-    run_state_ = RunState::STOPPED;
-  };
+  const auto on_complete_callback_ = [&]() { run_state_ = RunState::STOPPED; };
   legacy_hal::wifi_error legacy_status =
       legacy_hal_->stop(on_complete_callback_);
   if (legacy_status != legacy_hal::WIFI_SUCCESS) {
diff --git a/wifi/1.0/types.hal b/wifi/1.0/types.hal
index 83e6660..d90d5be 100644
--- a/wifi/1.0/types.hal
+++ b/wifi/1.0/types.hal
@@ -320,6 +320,11 @@
  */
 struct StaBackgroundScanBucketParameters {
   /**
+   * Bucket index. This index is used to report results in
+   * |StaScanData.bucketsScanned|.
+   */
+  uint32_t bucketIdx;
+  /**
    * Bands to scan or |BAND_UNSPECIFIED| if frequencies list must be used
    * instead.
    */
diff --git a/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
index dd1d1c4..2223022 100644
--- a/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
+++ b/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
@@ -278,8 +278,10 @@
    *        reject.
    * @param statusCode 802.11 code to indicate the reject reason.
    *        Refer to section 8.4.1.9 of IEEE 802.11 spec.
+   * @param timedOut Whether failure is due to timeout rather
+   *        than explicit rejection response from the AP.
    */
-  oneway onAssociationRejected(Bssid bssid, uint32_t statusCode);
+  oneway onAssociationRejected(Bssid bssid, uint32_t statusCode, bool timedOut);
 
   /**
    * Used to indicate the timeout of authentication to an AP.