Merge "Additonal usage note updates for Audio properties" into oc-mr1-dev
diff --git a/audio/2.0/config/audio_policy_configuration.xsd b/audio/2.0/config/audio_policy_configuration.xsd
index c94da80..eb59152 100644
--- a/audio/2.0/config/audio_policy_configuration.xsd
+++ b/audio/2.0/config/audio_policy_configuration.xsd
@@ -365,10 +365,10 @@
         </xs:restriction>
     </xs:simpleType>
     <xs:complexType name="profile">
-        <xs:attribute name="name" type="xs:token" use="required"/>
-        <xs:attribute name="format" type="audioFormat" use="required"/>
-        <xs:attribute name="samplingRates" type="samplingRates" use="required"/>
-        <xs:attribute name="channelMasks" type="channelMask" use="required"/>
+        <xs:attribute name="name" type="xs:token" use="optional"/>
+        <xs:attribute name="format" type="audioFormat" use="optional"/>
+        <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+        <xs:attribute name="channelMasks" type="channelMask" use="optional"/>
     </xs:complexType>
     <xs:simpleType name="gainMode">
         <xs:restriction base="xs:string">
diff --git a/compatibility_matrix.27.xml b/compatibility_matrix.27.xml
index 22ca426..5c81f26 100644
--- a/compatibility_matrix.27.xml
+++ b/compatibility_matrix.27.xml
@@ -71,7 +71,7 @@
             <instance>legacy/0</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="hidl" optional="true">
         <name>android.hardware.cas</name>
         <version>1.0</version>
         <interface>
diff --git a/compatibility_matrix.current.xml b/compatibility_matrix.current.xml
index 22ca426..5c81f26 100644
--- a/compatibility_matrix.current.xml
+++ b/compatibility_matrix.current.xml
@@ -71,7 +71,7 @@
             <instance>legacy/0</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="hidl" optional="true">
         <name>android.hardware.cas</name>
         <version>1.0</version>
         <interface>
diff --git a/wifi/1.1/default/hidl_return_util.h b/wifi/1.1/default/hidl_return_util.h
index 2f95c23..f36c8bd 100644
--- a/wifi/1.1/default/hidl_return_util.h
+++ b/wifi/1.1/default/hidl_return_util.h
@@ -55,6 +55,25 @@
   return Void();
 }
 
+// Use for HIDL methods which return only an instance of WifiStatus.
+// This version passes the global lock acquired to the body of the method.
+// Note: Only used by IWifi::stop() currently.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+Return<void> validateAndCallWithLock(
+    ObjT* obj,
+    WifiStatusCode status_code_if_invalid,
+    WorkFuncT&& work,
+    const std::function<void(const WifiStatus&)>& hidl_cb,
+    Args&&... args) {
+  auto lock = hidl_sync_util::acquireGlobalLock();
+  if (obj->isValid()) {
+    hidl_cb((obj->*work)(&lock, std::forward<Args>(args)...));
+  } else {
+    hidl_cb(createWifiStatus(status_code_if_invalid));
+  }
+  return Void();
+}
+
 // Use for HIDL methods which return instance of WifiStatus and a single return
 // value.
 template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
diff --git a/wifi/1.1/default/wifi.cpp b/wifi/1.1/default/wifi.cpp
index 8456b90..c46ef95 100644
--- a/wifi/1.1/default/wifi.cpp
+++ b/wifi/1.1/default/wifi.cpp
@@ -31,6 +31,7 @@
 namespace V1_1 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
+using hidl_return_util::validateAndCallWithLock;
 
 Wifi::Wifi()
     : legacy_hal_(new legacy_hal::WifiLegacyHal()),
@@ -64,8 +65,8 @@
 }
 
 Return<void> Wifi::stop(stop_cb hidl_status_cb) {
-  return validateAndCall(
-      this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, hidl_status_cb);
+  return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN,
+                                 &Wifi::stopInternal, hidl_status_cb);
 }
 
 Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
@@ -120,7 +121,8 @@
   return wifi_status;
 }
 
-WifiStatus Wifi::stopInternal() {
+WifiStatus Wifi::stopInternal(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
   if (run_state_ == RunState::STOPPED) {
     return createWifiStatus(WifiStatusCode::SUCCESS);
   } else if (run_state_ == RunState::STOPPING) {
@@ -133,7 +135,7 @@
     chip_->invalidate();
     chip_.clear();
   }
-  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController();
+  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
   if (wifi_status.code == WifiStatusCode::SUCCESS) {
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
       if (!callback->onStop().isOk()) {
@@ -180,11 +182,11 @@
   return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() {
+WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
   run_state_ = RunState::STOPPING;
-  const auto on_complete_callback_ = [&]() { run_state_ = RunState::STOPPED; };
   legacy_hal::wifi_error legacy_status =
-      legacy_hal_->stop(on_complete_callback_);
+      legacy_hal_->stop(lock, [&]() { run_state_ = RunState::STOPPED; });
   if (legacy_status != legacy_hal::WIFI_SUCCESS) {
     LOG(ERROR) << "Failed to stop legacy HAL: "
                << legacyErrorToString(legacy_status);
diff --git a/wifi/1.1/default/wifi.h b/wifi/1.1/default/wifi.h
index 1ade2d8..3a64cbd 100644
--- a/wifi/1.1/default/wifi.h
+++ b/wifi/1.1/default/wifi.h
@@ -61,12 +61,13 @@
   WifiStatus registerEventCallbackInternal(
       const sp<IWifiEventCallback>& event_callback);
   WifiStatus startInternal();
-  WifiStatus stopInternal();
+  WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
   std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
   std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id);
 
   WifiStatus initializeLegacyHal();
-  WifiStatus stopLegacyHalAndDeinitializeModeController();
+  WifiStatus stopLegacyHalAndDeinitializeModeController(
+      std::unique_lock<std::recursive_mutex>* lock);
 
   // Instance is created in this root level |IWifi| HIDL interface object
   // and shared with all the child HIDL interface objects.
diff --git a/wifi/1.1/default/wifi_legacy_hal.cpp b/wifi/1.1/default/wifi_legacy_hal.cpp
index 151a600..a6f6971 100644
--- a/wifi/1.1/default/wifi_legacy_hal.cpp
+++ b/wifi/1.1/default/wifi_legacy_hal.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <array>
+#include <chrono>
 
 #include <android-base/logging.h>
 #include <cutils/properties.h>
@@ -34,6 +35,7 @@
 static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
 static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
 static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxStopCompleteWaitMs = 50;
 
 // Helper function to create a non-const char* for legacy Hal API's.
 std::vector<char> makeCharVec(const std::string& str) {
@@ -53,7 +55,8 @@
 // Legacy HAL functions accept "C" style function pointers, so use global
 // functions to pass to the legacy HAL function and store the corresponding
 // std::function methods to be invoked.
-// Callback to be invoked once |stop| is complete.
+//
+// Callback to be invoked once |stop| is complete
 std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
 void onAsyncStopComplete(wifi_handle handle) {
   const auto lock = hidl_sync_util::acquireGlobalLock();
@@ -369,6 +372,7 @@
 }
 
 wifi_error WifiLegacyHal::stop(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
     const std::function<void()>& on_stop_complete_user_callback) {
   if (!is_started_) {
     LOG(DEBUG) << "Legacy HAL already stopped";
@@ -376,19 +380,27 @@
     return WIFI_SUCCESS;
   }
   LOG(DEBUG) << "Stopping legacy HAL";
-  on_stop_complete_internal_callback = [on_stop_complete_user_callback,
-                                        this](wifi_handle handle) {
+  on_stop_complete_internal_callback =
+      [on_stop_complete_user_callback, this](wifi_handle handle) {
     CHECK_EQ(global_handle_, handle) << "Handle mismatch";
+    LOG(INFO) << "Legacy HAL stop complete callback received";
     // Invalidate all the internal pointers now that the HAL is
     // stopped.
     invalidate();
     iface_tool_.SetWifiUpState(false);
     on_stop_complete_user_callback();
+    is_started_ = false;
   };
   awaiting_event_loop_termination_ = true;
   global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
+  const auto status = stop_wait_cv_.wait_for(
+      *lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
+      [this] { return !awaiting_event_loop_termination_; });
+  if (!status) {
+    LOG(ERROR) << "Legacy HAL stop failed or timed out";
+    return WIFI_ERROR_UNKNOWN;
+  }
   LOG(DEBUG) << "Legacy HAL stop complete";
-  is_started_ = false;
   return WIFI_SUCCESS;
 }
 
@@ -1257,11 +1269,13 @@
 void WifiLegacyHal::runEventLoop() {
   LOG(DEBUG) << "Starting legacy HAL event loop";
   global_func_table_.wifi_event_loop(global_handle_);
+  const auto lock = hidl_sync_util::acquireGlobalLock();
   if (!awaiting_event_loop_termination_) {
     LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
   }
   LOG(DEBUG) << "Legacy HAL event loop terminated";
   awaiting_event_loop_termination_ = false;
+  stop_wait_cv_.notify_one();
 }
 
 std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
diff --git a/wifi/1.1/default/wifi_legacy_hal.h b/wifi/1.1/default/wifi_legacy_hal.h
index caa1bd5..5498803 100644
--- a/wifi/1.1/default/wifi_legacy_hal.h
+++ b/wifi/1.1/default/wifi_legacy_hal.h
@@ -20,6 +20,7 @@
 #include <functional>
 #include <thread>
 #include <vector>
+#include <condition_variable>
 
 #include <wifi_system/interface_tool.h>
 
@@ -149,8 +150,10 @@
   wifi_error initialize();
   // Start the legacy HAL and the event looper thread.
   wifi_error start();
-  // Deinitialize the legacy HAL and stop the event looper thread.
-  wifi_error stop(const std::function<void()>& on_complete_callback);
+  // Deinitialize the legacy HAL and wait for the event loop thread to exit
+  // using a predefined timeout.
+  wifi_error stop(std::unique_lock<std::recursive_mutex>* lock,
+                  const std::function<void()>& on_complete_callback);
   // Wrappers for all the functions in the legacy HAL function table.
   std::pair<wifi_error, std::string> getDriverVersion();
   std::pair<wifi_error, std::string> getFirmwareVersion();
@@ -293,6 +296,7 @@
   wifi_interface_handle wlan_interface_handle_;
   // Flag to indicate if we have initiated the cleanup of legacy HAL.
   std::atomic<bool> awaiting_event_loop_termination_;
+  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_;