Only include chre_api_sensor.cc for SEE am: 1bac9db973

Original change: https://android-review.googlesource.com/c/platform/system/chre/+/1498208

Change-Id: I3786d557b93ac8d41e8d48af77a50fa54f184197
diff --git a/Android.mk b/Android.mk
index fa3a9c3..267c786 100644
--- a/Android.mk
+++ b/Android.mk
@@ -65,9 +65,9 @@
     system/chre/platform/shared/include \
     system/chre/platform/slpi/include \
     system/chre/util/include \
-    system/core/base/include \
+    system/libbase/include \
     system/core/libcutils/include \
-    system/core/liblog/include \
+    system/logging/liblog/include \
     system/core/libutils/include \
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/build/arch/x86.mk b/build/arch/x86.mk
index 695bd5a..0c5ce6b 100644
--- a/build/arch/x86.mk
+++ b/build/arch/x86.mk
@@ -9,7 +9,7 @@
          containing a path to the Android source tree. This is typically \
          provided by initializing the Android build environment.")
 endif
-export X86_TOOLS_PREFIX=$(ANDROID_BUILD_TOP)/prebuilts/clang/host/linux-x86/clang-r370808/bin/
+export X86_TOOLS_PREFIX=$(ANDROID_BUILD_TOP)/prebuilts/clang/host/linux-x86/clang-r383902c/bin/
 
 # x86 Tools ####################################################################
 
@@ -28,6 +28,9 @@
 # Enable position independence.
 TARGET_CFLAGS += -fpic
 
+# Disable double promotion warning for logging
+TARGET_CFLAGS += -Wno-double-promotion
+
 # x86 Shared Object Linker Flags ###############################################
 
 TARGET_SO_LDFLAGS += -shared
diff --git a/build/variant/google_x86_googletest.mk b/build/variant/google_x86_googletest.mk
index 3e6313b..eb48c7b 100644
--- a/build/variant/google_x86_googletest.mk
+++ b/build/variant/google_x86_googletest.mk
@@ -7,7 +7,14 @@
 TARGET_NAME = google_x86_googletest
 TARGET_CFLAGS = -DCHRE_MESSAGE_TO_HOST_MAX_SIZE=2048
 TARGET_VARIANT_SRCS = $(GOOGLE_X86_GOOGLETEST_SRCS)
+TARGET_VARIANT_SRCS += $(GOOGLETEST_COMMON_SRCS)
+
+ifeq ($(RUN_PAL_IMPL_TESTS), true)
+TARGET_VARIANT_SRCS += $(GOOGLETEST_PAL_IMPL_SRCS)
+else
 TARGET_VARIANT_SRCS += $(GOOGLETEST_SRCS)
+endif
+
 TARGET_PLATFORM_ID = 0x476f6f676c000001
 
 TARGET_CFLAGS += $(SIM_CFLAGS)
diff --git a/java/test/settings/src/com/google/android/chre/test/setting/ContextHubWifiSettingsTestExecutor.java b/java/test/settings/src/com/google/android/chre/test/setting/ContextHubWifiSettingsTestExecutor.java
index ae3a09b..50d740d 100644
--- a/java/test/settings/src/com/google/android/chre/test/setting/ContextHubWifiSettingsTestExecutor.java
+++ b/java/test/settings/src/com/google/android/chre/test/setting/ContextHubWifiSettingsTestExecutor.java
@@ -22,6 +22,7 @@
 import android.content.IntentFilter;
 import android.hardware.location.NanoAppBinary;
 import android.net.wifi.WifiManager;
+import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -37,6 +38,7 @@
  * A test to check for behavior when WiFi settings are changed.
  */
 public class ContextHubWifiSettingsTestExecutor {
+    private static final String TAG = "ContextHubWifiSettingsTestExecutor";
     private final ContextHubSettingsTestExecutor mExecutor;
 
     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -87,6 +89,9 @@
         mInitialLocationEnabled = mSettingsUtil.isLocationEnabled();
         mInitialWifiEnabled = mSettingsUtil.isWifiEnabled();
         mInitialWifiScanningAlwaysEnabled = mSettingsUtil.isWifiScanningAlwaysEnabled();
+        Log.d(TAG, "isLocationEnalbed=" + mInitialLocationEnabled
+                + ", isWifiEnabled=" + mInitialWifiEnabled
+                + ", isWifiScanningAlwaysEnabled=" + mInitialWifiScanningAlwaysEnabled);
         mExecutor.init();
     }
 
@@ -127,7 +132,7 @@
             wifiUpdateListener.mWifiLatch.await(30, TimeUnit.SECONDS);
 
             // Wait a few seconds to ensure setting is propagated to CHRE path
-            Thread.sleep(5000);
+            Thread.sleep(10000);
         } catch (InterruptedException e) {
             Assert.fail(e.getMessage());
         }
diff --git a/pal/pal.mk b/pal/pal.mk
index 0c92ecf..bf4dd46 100644
--- a/pal/pal.mk
+++ b/pal/pal.mk
@@ -9,5 +9,8 @@
 
 # GoogleTest Source Files ######################################################
 
-GOOGLETEST_SRCS += pal/tests/version_test.cc
-GOOGLETEST_SRCS += pal/tests/wwan_test.cc
+GOOGLETEST_CFLAGS += -Ipal/tests/include
+GOOGLETEST_SRCS += pal/tests/src/version_test.cc
+GOOGLETEST_SRCS += pal/tests/src/wwan_test.cc
+GOOGLETEST_PAL_IMPL_SRCS += pal/tests/src/gnss_pal_impl_test.cc
+GOOGLETEST_PAL_IMPL_SRCS += pal/tests/src/wifi_pal_impl_test.cc
diff --git a/pal/tests/include/gnss_pal_impl_test.h b/pal/tests/include/gnss_pal_impl_test.h
new file mode 100644
index 0000000..b69e960
--- /dev/null
+++ b/pal/tests/include/gnss_pal_impl_test.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 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 GNSSPAL_IMPL_TEST_H_
+#define GNSSPAL_IMPL_TEST_H_
+
+#include "chre/pal/gnss.h"
+#include "chre/platform/condition_variable.h"
+#include "chre/platform/mutex.h"
+#include "chre/util/fixed_size_vector.h"
+#include "chre/util/time.h"
+#include "gtest/gtest.h"
+
+namespace gnss_pal_impl_test {
+
+class PalGnssTest : public ::testing::Test {
+ public:
+  /**
+   * Implements CHRE PAL API callbacks
+   */
+  void requestStateResync();
+  void locationStatusChangeCallback(bool enabled, uint8_t errorCode);
+  void locationEventCallback(struct chreGnssLocationEvent *event);
+  void measurementStatusChangeCallback(bool enabled, uint8_t errorCode);
+  void measurementEventCallback(struct chreGnssDataEvent *event);
+
+ protected:
+  void SetUp() override;
+
+  void TearDown() override;
+
+  /**
+   * Prepares for a subsequent PAL API call that expects an async response.
+   */
+  void prepareForAsyncResponse() {
+    errorCode_ = CHRE_ERROR_LAST;
+  }
+
+  /**
+   * Waits for an async response by the PAL implementation (e.g. via location
+   * or measurement status change callback), and asserts that a success
+   * error code was received.
+   */
+  void waitForAsyncResponseAssertSuccess(chre::Nanoseconds timeoutNs);
+
+  //! The pointer to the CHRE PAL implementation API
+  const struct chrePalGnssApi *api_;
+
+  //! The error code of the most recent callback
+  uint8_t errorCode_ = CHRE_ERROR_LAST;
+
+  //! True if location session is currently enabled
+  bool locationSessionEnabled_ = false;
+
+  //! True if location session is currently enabled
+  bool measurementSessionEnabled_ = false;
+
+  //! A list to store the location events
+  static constexpr size_t kEventArraySize = 5;
+  chre::FixedSizeVector<chreGnssLocationEvent *, kEventArraySize>
+      locationEventVector_;
+  chre::FixedSizeVector<chreGnssDataEvent *, kEventArraySize>
+      measurementEventVector_;
+
+  //! Mutex to protect class variables
+  chre::Mutex mutex_;
+  chre::ConditionVariable condVar_;
+};
+
+}  // namespace gnss_pal_impl_test
+
+#endif  // GNSSPAL_IMPL_TEST_H_
diff --git a/pal/tests/include/wifi_pal_impl_test.h b/pal/tests/include/wifi_pal_impl_test.h
new file mode 100644
index 0000000..2188ea6
--- /dev/null
+++ b/pal/tests/include/wifi_pal_impl_test.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2020 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_PAL_IMPL_TEST_H_
+#define WIFI_PAL_IMPL_TEST_H_
+
+#include "chre/pal/wifi.h"
+#include "chre/platform/condition_variable.h"
+#include "chre/platform/mutex.h"
+#include "chre/util/dynamic_vector.h"
+#include "chre/util/optional.h"
+#include "chre/util/time.h"
+#include "gtest/gtest.h"
+
+namespace wifi_pal_impl_test {
+
+class PalWifiTest : public ::testing::Test {
+ public:
+  /**
+   * Implements CHRE PAL API callbacks
+   */
+  void scanMonitorStatusChangeCallback(bool enabled, uint8_t errorCode);
+  void scanResponseCallback(bool pending, uint8_t errorCode);
+  void scanEventCallback(struct chreWifiScanEvent *event);
+  void rangingEventCallback(uint8_t errorCode,
+                            struct chreWifiRangingEvent *event);
+
+ protected:
+  void SetUp() override;
+
+  void TearDown() override;
+
+  /**
+   * Validates an incoming WiFi scan event.
+   *
+   * @param event The WiFi scan event.
+   */
+  void validateWifiScanEvent(const chreWifiScanEvent &event);
+
+  /**
+   * Prepares for a subsequent PAL API call that expects an async response.
+   */
+  void prepareForAsyncResponse() {
+    errorCode_ = CHRE_ERROR_LAST;
+  }
+
+  /**
+   * Waits for an async response by the PAL implementation (e.g. via scan
+   * response/monitor status change callback), and asserts that a success
+   * error code was received.
+   */
+  void waitForAsyncResponseAssertSuccess(chre::Nanoseconds timeoutNs);
+
+  //! The pointer to the CHRE PAL implementation API
+  const struct chrePalWifiApi *api_;
+
+  //! The error code of the most recent callback
+  uint8_t errorCode_ = CHRE_ERROR_LAST;
+
+  //! The number of scan events currently stored
+  uint32_t numScanResultCount_ = 0;
+
+  //! True if the last scan event has been received
+  bool lastScanEventReceived_ = false;
+
+  //! A list to store the scan results
+  chre::DynamicVector<chreWifiScanEvent *> scanEventList_;
+
+  //! Stores active scan params
+  chre::Optional<chreWifiScanParams> scanParams_;
+
+  //! The last scan event index received, UINT8_MAX if invalid
+  uint8_t lastEventIndex_;
+
+  //! True if scan monitoring is currently enabled
+  bool scanMonitorEnabled_ = false;
+
+  //! Mutex to protect class variables
+  chre::Mutex mutex_;
+  chre::ConditionVariable condVar_;
+};
+
+}  // namespace wifi_pal_impl_test
+
+#endif  // WIFI_PAL_IMPL_TEST_H_
diff --git a/pal/tests/src/gnss_pal_impl_test.cc b/pal/tests/src/gnss_pal_impl_test.cc
new file mode 100644
index 0000000..bbb92e9
--- /dev/null
+++ b/pal/tests/src/gnss_pal_impl_test.cc
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2020 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 "gnss_pal_impl_test.h"
+
+#include "chre/platform/log.h"
+#include "chre/platform/shared/pal_system_api.h"
+#include "chre/platform/system_time.h"
+#include "chre/util/lock_guard.h"
+
+#include <cinttypes>
+
+//! Flag to require GNSS location sessions capability to be enabled for the test
+//! to pass. Set to false to allow tests to pass on disabled platforms.
+//! Note that it is required to run this test where location can be acquired.
+//! The constants kGnssEventTimeoutNs and kEventArraySize may be tuned if
+//! applicable.
+#ifndef PAL_IMPL_TEST_GNSS_LOCATION_REQUIRED
+#define PAL_IMPL_TEST_GNSS_LOCATION_REQUIRED true
+#endif
+
+//! Same as above for GNSS measurement sessions.
+#ifndef PAL_IMPL_TEST_GNSS_MEASUREMENTS_REQUIRED
+#define PAL_IMPL_TEST_GNSS_MEASUREMENTS_REQUIRED true
+#endif
+
+namespace gnss_pal_impl_test {
+
+namespace {
+
+using ::chre::Nanoseconds;
+using ::chre::Seconds;
+using ::chre::SystemTime;
+
+//! A pointer to the current test running
+gnss_pal_impl_test::PalGnssTest *gTest = nullptr;
+
+//! Timeout as specified by the CHRE API
+const Nanoseconds kGnssAsyncResultTimeoutNs =
+    Nanoseconds(CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS);
+
+//! Timeout to wait for kEventArraySize events.
+const Nanoseconds kGnssEventTimeoutNs = Seconds(60);
+
+void chrePalRequestStateResync() {
+  if (gTest != nullptr) {
+    gTest->requestStateResync();
+  }
+}
+
+void chrePalLocationStatusChangeCallback(bool enabled, uint8_t errorCode) {
+  if (gTest != nullptr) {
+    gTest->locationStatusChangeCallback(enabled, errorCode);
+  }
+}
+
+void chrePalLocationEventCallback(struct chreGnssLocationEvent *event) {
+  if (gTest != nullptr) {
+    gTest->locationEventCallback(event);
+  }
+}
+
+void chrePalMeasurementStatusChangeCallback(bool enabled, uint8_t errorCode) {
+  if (gTest != nullptr) {
+    gTest->measurementStatusChangeCallback(enabled, errorCode);
+  }
+}
+
+void chrePalMeasurementEventCallback(struct chreGnssDataEvent *event) {
+  if (gTest != nullptr) {
+    gTest->measurementEventCallback(event);
+  }
+}
+
+void logLocationEvent(const struct chreGnssLocationEvent &event) {
+  LOGI("Received location: %" PRId32 ", %" PRId32, event.latitude_deg_e7,
+       event.longitude_deg_e7);
+  LOGI("  timestamp (ms): %" PRIu64, event.timestamp);
+  LOGI("  altitude (m): %f", event.altitude);
+  LOGI("  speed (m/s): %f", event.speed);
+  LOGI("  bearing (deg): %f", event.bearing);
+  LOGI("  accuracy: %f", event.accuracy);
+  LOGI("  flags: 0x%" PRIx16, event.flags);
+  LOGI("  altitude_accuracy: %f", event.altitude_accuracy);
+  LOGI("  speed_accuracy: %f", event.speed_accuracy);
+  LOGI("  bearing_accuracy: %f", event.bearing_accuracy);
+}
+
+void validateLocationEvent(const struct chreGnssLocationEvent &event) {
+  static uint64_t sLastTimestampNs = 0;
+  EXPECT_GE(event.timestamp, sLastTimestampNs);
+  sLastTimestampNs = event.timestamp;
+  if (event.flags & CHRE_GPS_LOCATION_HAS_LAT_LONG) {
+    EXPECT_GE(event.latitude_deg_e7, -90 * 1e7);
+    EXPECT_LE(event.latitude_deg_e7, 90 * 1e7);
+    EXPECT_GE(event.longitude_deg_e7, -180 * 1e7);
+    EXPECT_LE(event.longitude_deg_e7, 180 * 1e7);
+  }
+  if (event.flags & CHRE_GPS_LOCATION_HAS_BEARING) {
+    EXPECT_GE(event.bearing, 0);
+    EXPECT_LT(event.bearing, 360);  // [0, 360) per API
+  }
+}
+
+void logMeasurementEvent(const struct chreGnssDataEvent &event) {
+  LOGI("Received data: %" PRIu8 " measurements", event.measurement_count);
+
+  for (uint8_t i = 0; i < event.measurement_count; i++) {
+    LOGI("%" PRIu8 ": const %" PRIu8 ", cn0 %.2f, freq %.3f MHz", i,
+         event.measurements[i].constellation, event.measurements[i].c_n0_dbhz,
+         event.measurements[i].carrier_frequency_hz / 1e6);
+  }
+}
+
+void validateMeasurementEvent(const struct chreGnssDataEvent &event) {
+  EXPECT_GE(event.measurement_count, 0);
+  EXPECT_LE(event.measurement_count, CHRE_GNSS_MAX_MEASUREMENT);
+  if (event.measurement_count > 0) {
+    EXPECT_NE(event.measurements, nullptr);
+  }
+
+  static int64_t sLastClockTimeNs = INT64_MIN;
+  EXPECT_GE(event.clock.time_ns, sLastClockTimeNs);
+  sLastClockTimeNs = event.clock.time_ns;
+
+  for (uint8_t i = 0; i < event.measurement_count; i++) {
+    EXPECT_GE(event.measurements[i].c_n0_dbhz, 0);
+    EXPECT_LE(event.measurements[i].c_n0_dbhz, 63);
+  }
+}
+
+}  // anonymous namespace
+
+void PalGnssTest::SetUp() {
+  api_ = chrePalGnssGetApi(CHRE_PAL_GNSS_API_CURRENT_VERSION);
+  ASSERT_NE(api_, nullptr);
+  EXPECT_EQ(api_->moduleVersion, CHRE_PAL_GNSS_API_CURRENT_VERSION);
+
+  // Open the PAL API
+  static const struct chrePalGnssCallbacks kCallbacks = {
+      .requestStateResync = chrePalRequestStateResync,
+      .locationStatusChangeCallback = chrePalLocationStatusChangeCallback,
+      .locationEventCallback = chrePalLocationEventCallback,
+      .measurementStatusChangeCallback = chrePalMeasurementStatusChangeCallback,
+      .measurementEventCallback = chrePalMeasurementEventCallback,
+  };
+  ASSERT_TRUE(api_->open(&chre::gChrePalSystemApi, &kCallbacks));
+  gTest = this;
+
+  errorCode_ = CHRE_ERROR_LAST;
+  locationSessionEnabled_ = false;
+  locationEventVector_.resize(0);
+  measurementSessionEnabled_ = false;
+  measurementEventVector_.resize(0);
+}
+
+void PalGnssTest::TearDown() {
+  gTest = nullptr;
+  api_->close();
+}
+
+void PalGnssTest::requestStateResync() {
+  // TODO:
+}
+
+void PalGnssTest::locationStatusChangeCallback(bool enabled,
+                                               uint8_t errorCode) {
+  LOGI("Received location status change with enabled %d error %" PRIu8, enabled,
+       errorCode);
+  if (errorCode == CHRE_ERROR_LAST) {
+    LOGE("Received CHRE_ERROR_LAST");
+    errorCode = CHRE_ERROR;
+  }
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+  errorCode_ = errorCode;
+  locationSessionEnabled_ = enabled;
+  condVar_.notify_one();
+}
+
+void PalGnssTest::locationEventCallback(struct chreGnssLocationEvent *event) {
+  LOGI("Received location event");
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+  if (!locationEventVector_.full()) {
+    locationEventVector_.push_back(event);
+    if (locationEventVector_.full()) {
+      condVar_.notify_one();
+    }
+  }
+}
+
+void PalGnssTest::measurementStatusChangeCallback(bool enabled,
+                                                  uint8_t errorCode) {
+  LOGI("Received measurement status change with enabled %d error %" PRIu8,
+       enabled, errorCode);
+  if (errorCode == CHRE_ERROR_LAST) {
+    LOGE("Received CHRE_ERROR_LAST");
+    errorCode = CHRE_ERROR;
+  }
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+  errorCode_ = errorCode;
+  measurementSessionEnabled_ = enabled;
+  condVar_.notify_one();
+}
+
+void PalGnssTest::measurementEventCallback(struct chreGnssDataEvent *event) {
+  LOGI("Received measurement event");
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+  if (!measurementEventVector_.full()) {
+    measurementEventVector_.push_back(event);
+    if (measurementEventVector_.full()) {
+      condVar_.notify_one();
+    }
+  }
+}
+
+void PalGnssTest::waitForAsyncResponseAssertSuccess(
+    chre::Nanoseconds timeoutNs) {
+  bool waitSuccess = true;
+  while (errorCode_ == CHRE_ERROR_LAST && waitSuccess) {
+    waitSuccess = condVar_.wait_for(mutex_, timeoutNs);
+  }
+  ASSERT_TRUE(waitSuccess);
+  ASSERT_EQ(errorCode_, CHRE_ERROR_NONE);
+}
+
+TEST_F(PalGnssTest, LocationSessionTest) {
+  bool hasLocationCapability =
+      ((api_->getCapabilities() & CHRE_GNSS_CAPABILITIES_LOCATION) ==
+       CHRE_GNSS_CAPABILITIES_LOCATION);
+#if PAL_IMPL_TEST_GNSS_LOCATION_REQUIRED
+  ASSERT_TRUE(hasLocationCapability);
+#else
+  if (!hasLocationCapability) {
+    GTEST_SKIP();
+  }
+#endif
+
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+
+  prepareForAsyncResponse();
+  ASSERT_TRUE(api_->controlLocationSession(
+      true /* enable */, 1000 /* minIntervalMs */, 0 /* minTimeToNextFixMs */));
+  waitForAsyncResponseAssertSuccess(kGnssAsyncResultTimeoutNs);
+  ASSERT_TRUE(locationSessionEnabled_);
+
+  bool waitSuccess = true;
+  while (!locationEventVector_.full() && waitSuccess) {
+    waitSuccess = condVar_.wait_for(mutex_, kGnssEventTimeoutNs);
+  }
+
+  for (size_t i = 0; i < locationEventVector_.size(); i++) {
+    logLocationEvent(*locationEventVector_[i]);
+    validateLocationEvent(*locationEventVector_[i]);
+    api_->releaseLocationEvent(locationEventVector_[i]);
+  }
+  EXPECT_TRUE(locationEventVector_.full());
+
+  prepareForAsyncResponse();
+  ASSERT_TRUE(api_->controlLocationSession(
+      false /* enable */, 0 /* minIntervalMs */, 0 /* minTimeToNextFixMs */));
+  waitForAsyncResponseAssertSuccess(kGnssAsyncResultTimeoutNs);
+  ASSERT_FALSE(locationSessionEnabled_);
+}
+
+TEST_F(PalGnssTest, MeasurementSessionTest) {
+  bool hasMeasurementCapability =
+      ((api_->getCapabilities() & CHRE_GNSS_CAPABILITIES_MEASUREMENTS) ==
+       CHRE_GNSS_CAPABILITIES_MEASUREMENTS);
+#if PAL_IMPL_TEST_GNSS_MEAUSUREMENT_REQUIRED
+  ASSERT_TRUE(hasMeasurementCapability);
+#else
+  if (!hasMeasurementCapability) {
+    GTEST_SKIP();
+  }
+#endif
+
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+
+  prepareForAsyncResponse();
+  ASSERT_TRUE(api_->controlMeasurementSession(true /* enable */,
+                                              1000 /* minIntervalMs */));
+  waitForAsyncResponseAssertSuccess(kGnssAsyncResultTimeoutNs);
+  ASSERT_TRUE(measurementSessionEnabled_);
+
+  bool waitSuccess = true;
+  while (!measurementEventVector_.full() && waitSuccess) {
+    waitSuccess = condVar_.wait_for(mutex_, kGnssEventTimeoutNs);
+  }
+  EXPECT_TRUE(measurementEventVector_.full());
+
+  for (size_t i = 0; i < measurementEventVector_.size(); i++) {
+    logMeasurementEvent(*measurementEventVector_[i]);
+    validateMeasurementEvent(*measurementEventVector_[i]);
+    api_->releaseMeasurementDataEvent(measurementEventVector_[i]);
+  }
+
+  prepareForAsyncResponse();
+  ASSERT_TRUE(api_->controlMeasurementSession(false /* enable */,
+                                              0 /* minIntervalMs */));
+  waitForAsyncResponseAssertSuccess(kGnssAsyncResultTimeoutNs);
+  ASSERT_FALSE(measurementSessionEnabled_);
+}
+
+}  // namespace gnss_pal_impl_test
diff --git a/pal/tests/version_test.cc b/pal/tests/src/version_test.cc
similarity index 100%
rename from pal/tests/version_test.cc
rename to pal/tests/src/version_test.cc
diff --git a/pal/tests/src/wifi_pal_impl_test.cc b/pal/tests/src/wifi_pal_impl_test.cc
new file mode 100644
index 0000000..a266a6b
--- /dev/null
+++ b/pal/tests/src/wifi_pal_impl_test.cc
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2020 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 "wifi_pal_impl_test.h"
+
+#include "chre/platform/log.h"
+#include "chre/platform/shared/pal_system_api.h"
+#include "chre/platform/system_time.h"
+#include "chre/util/lock_guard.h"
+#include "chre/util/nanoapp/wifi.h"
+
+#include <cinttypes>
+
+// Flag to require on-demand WiFi scanning capability to be enabled for the test
+// to pass. Set to false to allow tests to pass on disabled platforms.
+#ifndef PAL_IMPL_TEST_WIFI_ON_DEMAND_SCAN_REQUIRED
+#define PAL_IMPL_TEST_WIFI_ON_DEMAND_SCAN_REQUIRED true
+#endif
+
+// Same as above for scan monitoring.
+#ifndef PAL_IMPL_TEST_WIFI_SCAN_MONITORING_REQUIRED
+#define PAL_IMPL_TEST_WIFI_SCAN_MONITORING_REQUIRED true
+#endif
+
+namespace wifi_pal_impl_test {
+
+namespace {
+
+using ::chre::Nanoseconds;
+using ::chre::Seconds;
+using ::chre::SystemTime;
+
+//! A pointer to the current test running
+wifi_pal_impl_test::PalWifiTest *gTest = nullptr;
+
+//! Timeout as specified by the CHRE API
+const Nanoseconds kAsyncResultTimeoutNs =
+    Nanoseconds(CHRE_ASYNC_RESULT_TIMEOUT_NS);
+const Nanoseconds kScanResultTimeoutNs =
+    Nanoseconds(CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS);
+
+void chrePalScanMonitorStatusChangeCallback(bool enabled, uint8_t errorCode) {
+  if (gTest != nullptr) {
+    gTest->scanMonitorStatusChangeCallback(enabled, errorCode);
+  }
+}
+
+void chrePalScanResponseCallback(bool pending, uint8_t errorCode) {
+  if (gTest != nullptr) {
+    gTest->scanResponseCallback(pending, errorCode);
+  }
+}
+
+void chrePalScanEventCallback(struct chreWifiScanEvent *event) {
+  if (gTest != nullptr) {
+    gTest->scanEventCallback(event);
+  }
+}
+
+void chrePalRangingEventCallback(uint8_t errorCode,
+                                 struct chreWifiRangingEvent *event) {
+  if (gTest != nullptr) {
+    gTest->rangingEventCallback(errorCode, event);
+  }
+}
+
+void logChreWifiResult(const chreWifiScanResult &result) {
+  const char *ssidStr = "<non-printable>";
+  char ssidBuffer[chre::kMaxSsidStrLen];
+  if (result.ssidLen == 0) {
+    ssidStr = "<empty>";
+  } else if (chre::parseSsidToStr(ssidBuffer, sizeof(ssidBuffer), result.ssid,
+                                  result.ssidLen)) {
+    ssidStr = ssidBuffer;
+  }
+
+  LOGI("Found network with SSID: %s", ssidStr);
+  const char *bssidStr = "<non-printable>";
+  char bssidBuffer[chre::kBssidStrLen];
+  if (chre::parseBssidToStr(result.bssid, bssidBuffer, sizeof(bssidBuffer))) {
+    bssidStr = bssidBuffer;
+  }
+
+  LOGI("  age (ms): %" PRIu32, result.ageMs);
+  LOGI("  capability info: 0x%" PRIx16, result.capabilityInfo);
+  LOGI("  bssid: %s", bssidStr);
+  LOGI("  flags: 0x%" PRIx8, result.flags);
+  LOGI("  rssi: %" PRId8 "dBm", result.rssi);
+  LOGI("  band: %s (%" PRIu8 ")", chre::parseChreWifiBand(result.band),
+       result.band);
+  LOGI("  primary channel: %" PRIu32, result.primaryChannel);
+  LOGI("  center frequency primary: %" PRIu32, result.centerFreqPrimary);
+  LOGI("  center frequency secondary: %" PRIu32, result.centerFreqSecondary);
+  LOGI("  channel width: %" PRIu8, result.channelWidth);
+  LOGI("  security mode: 0x%" PRIx8, result.securityMode);
+}
+
+}  // anonymous namespace
+
+void PalWifiTest::SetUp() {
+  api_ = chrePalWifiGetApi(CHRE_PAL_WIFI_API_CURRENT_VERSION);
+  ASSERT_NE(api_, nullptr);
+  EXPECT_EQ(api_->moduleVersion, CHRE_PAL_WIFI_API_CURRENT_VERSION);
+
+  // Open the PAL API
+  static const struct chrePalWifiCallbacks kCallbacks = {
+      .scanMonitorStatusChangeCallback = chrePalScanMonitorStatusChangeCallback,
+      .scanResponseCallback = chrePalScanResponseCallback,
+      .scanEventCallback = chrePalScanEventCallback,
+      .rangingEventCallback = chrePalRangingEventCallback,
+  };
+  ASSERT_TRUE(api_->open(&chre::gChrePalSystemApi, &kCallbacks));
+  gTest = this;
+
+  errorCode_ = CHRE_ERROR_LAST;
+  numScanResultCount_ = 0;
+  lastScanEventReceived_ = false;
+  scanEventList_.clear();
+  scanParams_.reset();
+  lastEventIndex_ = UINT8_MAX;
+  scanMonitorEnabled_ = false;
+}
+
+void PalWifiTest::TearDown() {
+  gTest = nullptr;
+  api_->close();
+}
+
+void PalWifiTest::scanMonitorStatusChangeCallback(bool enabled,
+                                                  uint8_t errorCode) {
+  LOGI("Received scan monitor response with enabled %d error %" PRIu8, enabled,
+       errorCode);
+  if (errorCode == CHRE_ERROR_LAST) {
+    LOGE("Received CHRE_ERROR_LAST");
+    errorCode = CHRE_ERROR;
+  }
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+  scanMonitorEnabled_ = enabled;
+  errorCode_ = errorCode;
+  condVar_.notify_one();
+}
+
+void PalWifiTest::scanResponseCallback(bool pending, uint8_t errorCode) {
+  LOGI("Received scan response with pending %d error %" PRIu8, pending,
+       errorCode);
+  if (errorCode == CHRE_ERROR_LAST) {
+    LOGE("Received CHRE_ERROR_LAST");
+    errorCode = CHRE_ERROR;
+  }
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+  errorCode_ = errorCode;
+  condVar_.notify_one();
+}
+
+void PalWifiTest::scanEventCallback(struct chreWifiScanEvent *event) {
+  if (event == nullptr) {
+    LOGE("Got null scan event");
+  } else {
+    {
+      chre::LockGuard<chre::Mutex> lock(mutex_);
+      scanEventList_.push_back(event);
+      numScanResultCount_ += event->resultCount;
+      lastScanEventReceived_ = (numScanResultCount_ == event->resultTotal);
+    }
+
+    condVar_.notify_one();
+  }
+}
+
+void PalWifiTest::rangingEventCallback(uint8_t errorCode,
+                                       struct chreWifiRangingEvent *event) {
+  // TODO:
+}
+
+void PalWifiTest::validateWifiScanEvent(const chreWifiScanEvent &event) {
+  if (scanParams_.has_value()) {
+    EXPECT_EQ(event.scanType, scanParams_->scanType);
+    EXPECT_GE(event.referenceTime,
+              chreGetTime() - (scanParams_->maxScanAgeMs *
+                               chre::kOneMillisecondInNanoseconds));
+    EXPECT_EQ(event.radioChainPref, scanParams_->radioChainPref);
+    EXPECT_EQ(event.eventIndex, static_cast<uint8_t>(lastEventIndex_ + 1));
+  }
+}
+
+void PalWifiTest::waitForAsyncResponseAssertSuccess(
+    chre::Nanoseconds timeoutNs) {
+  bool waitSuccess = true;
+  while (errorCode_ == CHRE_ERROR_LAST && waitSuccess) {
+    waitSuccess = condVar_.wait_for(mutex_, timeoutNs);
+  }
+  ASSERT_TRUE(waitSuccess);
+  ASSERT_EQ(errorCode_, CHRE_ERROR_NONE);
+}
+
+TEST_F(PalWifiTest, ScanAsyncTest) {
+  bool hasOnDemandScanCapability =
+      (api_->getCapabilities() & CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN) ==
+      CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN;
+#if PAL_IMPL_TEST_WIFI_ON_DEMAND_SCAN_REQUIRED
+  ASSERT_TRUE(hasOnDemandScanCapability);
+#else
+  if (!hasOnDemandScanCapability) {
+    GTEST_SKIP();
+  }
+#endif
+
+  // Request a WiFi scan
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+
+  struct chreWifiScanParams params = {};
+  params.scanType = CHRE_WIFI_SCAN_TYPE_ACTIVE;
+  params.maxScanAgeMs = 5000;  // 5 seconds
+  params.frequencyListLen = 0;
+  params.ssidListLen = 0;
+  params.radioChainPref = CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT;
+  scanParams_ = params;
+
+  prepareForAsyncResponse();
+  ASSERT_TRUE(api_->requestScan(&scanParams_.value()));
+  waitForAsyncResponseAssertSuccess(kScanResultTimeoutNs);
+
+  // The CHRE API only poses timeout requirements on the async response. Use
+  // the same timeout to receive the scan results to avoid blocking forever.
+  bool waitSuccess = true;
+  while (!lastScanEventReceived_ && waitSuccess) {
+    waitSuccess = condVar_.wait_for(mutex_, kScanResultTimeoutNs);
+  }
+
+  for (auto *event : scanEventList_) {
+    for (uint8_t i = 0; i < event->resultCount; i++) {
+      const chreWifiScanResult &result = event->results[i];
+      logChreWifiResult(result);
+    }
+    validateWifiScanEvent(*event);
+
+    lastEventIndex_ = event->eventIndex;
+    api_->releaseScanEvent(event);
+  }
+
+  EXPECT_TRUE(lastScanEventReceived_);
+  EXPECT_GT(numScanResultCount_, 0);
+}
+
+// Note: This test only verifies that the scan monitor succeeds according
+// to the async response.
+TEST_F(PalWifiTest, ScanMonitorTest) {
+  bool hasScanMonitoringCapability =
+      (api_->getCapabilities() & CHRE_WIFI_CAPABILITIES_SCAN_MONITORING) ==
+      CHRE_WIFI_CAPABILITIES_SCAN_MONITORING;
+#if PAL_IMPL_TEST_WIFI_SCAN_MONITORING_REQUIRED
+  ASSERT_TRUE(hasScanMonitoringCapability);
+#else
+  if (!hasScanMonitoringCapability) {
+    GTEST_SKIP();
+  }
+#endif
+
+  chre::LockGuard<chre::Mutex> lock(mutex_);
+
+  prepareForAsyncResponse();
+  ASSERT_TRUE(api_->configureScanMonitor(true /* enable */));
+  waitForAsyncResponseAssertSuccess(kAsyncResultTimeoutNs);
+  ASSERT_TRUE(scanMonitorEnabled_);
+
+  prepareForAsyncResponse();
+  ASSERT_TRUE(api_->configureScanMonitor(false /* enable */));
+  waitForAsyncResponseAssertSuccess(kAsyncResultTimeoutNs);
+  ASSERT_FALSE(scanMonitorEnabled_);
+}
+
+}  // namespace wifi_pal_impl_test
diff --git a/pal/tests/wwan_test.cc b/pal/tests/src/wwan_test.cc
similarity index 100%
rename from pal/tests/wwan_test.cc
rename to pal/tests/src/wwan_test.cc
diff --git a/platform/platform.mk b/platform/platform.mk
index 2ce2891..fa469c1 100644
--- a/platform/platform.mk
+++ b/platform/platform.mk
@@ -245,10 +245,10 @@
 
 # Add in host sources to allow the executable to both be a socket server and
 # CHRE implementation.
-GOOGLE_ARM64_ANDROID_CFLAGS += -I$(ANDROID_BUILD_TOP)/system/core/base/include
+GOOGLE_ARM64_ANDROID_CFLAGS += -I$(ANDROID_BUILD_TOP)/system/libbase/include
 GOOGLE_ARM64_ANDROID_CFLAGS += -I$(ANDROID_BUILD_TOP)/system/core/libcutils/include
 GOOGLE_ARM64_ANDROID_CFLAGS += -I$(ANDROID_BUILD_TOP)/system/core/libutils/include
-GOOGLE_ARM64_ANDROID_CFLAGS += -I$(ANDROID_BUILD_TOP)/system/core/liblog/include
+GOOGLE_ARM64_ANDROID_CFLAGS += -I$(ANDROID_BUILD_TOP)/system/logging/liblog/include
 GOOGLE_ARM64_ANDROID_CFLAGS += -Ihost/common/include
 
 # Also add the linux sources to fall back to the default Linux implementation.
@@ -260,7 +260,7 @@
 # Android-specific Source Files ################################################
 
 ANDROID_CUTILS_TOP = $(ANDROID_BUILD_TOP)/system/core/libcutils
-ANDROID_LOG_TOP = $(ANDROID_BUILD_TOP)/system/core/liblog
+ANDROID_LOG_TOP = $(ANDROID_BUILD_TOP)/system/logging/liblog
 
 GOOGLE_ARM64_ANDROID_SRCS += $(ANDROID_CUTILS_TOP)/sockets_unix.cpp
 GOOGLE_ARM64_ANDROID_SRCS += $(ANDROID_CUTILS_TOP)/android_get_control_file.cpp
@@ -289,6 +289,6 @@
 
 # GoogleTest Source Files ######################################################
 
-GOOGLETEST_SRCS += platform/linux/assert.cc
-GOOGLETEST_SRCS += platform/linux/audio_source.cc
-GOOGLETEST_SRCS += platform/linux/platform_audio.cc
+GOOGLETEST_COMMON_SRCS += platform/linux/assert.cc
+GOOGLETEST_COMMON_SRCS += platform/linux/audio_source.cc
+GOOGLETEST_COMMON_SRCS += platform/linux/platform_audio.cc
diff --git a/run_pal_impl_tests.sh b/run_pal_impl_tests.sh
new file mode 100755
index 0000000..4b0daed
--- /dev/null
+++ b/run_pal_impl_tests.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Quit if any command produces an error.
+set -e
+
+# Build and run the CHRE unit test binary.
+JOB_COUNT=$((`grep -c ^processor /proc/cpuinfo`))
+
+# Export the variant Makefile.
+export CHRE_VARIANT_MK_INCLUDES="$CHRE_VARIANT_MK_INCLUDES \
+  variant/googletest/variant.mk"
+
+export RUN_PAL_IMPL_TESTS=true
+
+make clean
+make google_x86_googletest_debug -j$JOB_COUNT
+./out/google_x86_googletest_debug/libchre $1