Merge "Implement Gnss::start() and Gnss::stop()" into pi-dev
diff --git a/gnss/1.1/default/Gnss.cpp b/gnss/1.1/default/Gnss.cpp
index 308ba70..98a79ee 100644
--- a/gnss/1.1/default/Gnss.cpp
+++ b/gnss/1.1/default/Gnss.cpp
@@ -1,7 +1,8 @@
 #define LOG_TAG "Gnss"
 
-#include "Gnss.h"
 #include <log/log.h>
+
+#include "Gnss.h"
 #include "GnssConfiguration.h"
 #include "GnssMeasurement.h"
 
@@ -11,20 +12,46 @@
 namespace V1_1 {
 namespace implementation {
 
+const uint32_t MIN_INTERVAL_MILLIS = 100;
+sp<::android::hardware::gnss::V1_1::IGnssCallback> Gnss::sGnssCallback = nullptr;
+
+Gnss::Gnss() : mMinIntervalMs(1000) {}
+
+Gnss::~Gnss() {
+    stop();
+}
+
 // Methods from ::android::hardware::gnss::V1_0::IGnss follow.
 Return<bool> Gnss::setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback>&) {
-    // TODO implement
-    return bool{};
+    // Mock handles only new callback (see setCallback1_1) coming from Android P+
+    return false;
 }
 
 Return<bool> Gnss::start() {
-    // TODO implement
-    return bool{};
+    if (mIsActive) {
+        ALOGW("Gnss has started. Restarting...");
+        stop();
+    }
+
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            V1_0::GnssLocation location = this->getMockLocation();
+            this->reportLocation(location);
+
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+        }
+    });
+
+    return true;
 }
 
 Return<bool> Gnss::stop() {
-    // TODO implement
-    return bool{};
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+    return true;
 }
 
 Return<void> Gnss::cleanup() {
@@ -107,18 +134,43 @@
 }
 
 // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
-Return<bool> Gnss::setCallback_1_1(const sp<::android::hardware::gnss::V1_1::IGnssCallback>&) {
-    ALOGI("Gnss::setCallback_1_1");
-    // TODO implement
-    return bool{};
+Return<bool> Gnss::setCallback_1_1(
+    const sp<::android::hardware::gnss::V1_1::IGnssCallback>& callback) {
+    if (callback == nullptr) {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sGnssCallback = callback;
+
+    uint32_t capabilities = 0x0;
+    auto ret = sGnssCallback->gnssSetCapabilitesCb(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
+
+    ret = sGnssCallback->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    auto gnssName = "Google Mock GNSS Implementation v1.1";
+    ret = sGnssCallback->gnssNameCb(gnssName);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    return true;
 }
 
 Return<bool> Gnss::setPositionMode_1_1(
     ::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,
-    ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t, uint32_t,
-    bool) {
-    // TODO implement
-    return bool{};
+    ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs,
+    uint32_t, uint32_t, bool) {
+    mMinIntervalMs = (minIntervalMs < MIN_INTERVAL_MILLIS) ? MIN_INTERVAL_MILLIS : minIntervalMs;
+    return true;
 }
 
 Return<sp<::android::hardware::gnss::V1_1::IGnssConfiguration>>
@@ -138,7 +190,30 @@
     return bool{};
 }
 
-// Methods from ::android::hidl::base::V1_0::IBase follow.
+Return<V1_0::GnssLocation> Gnss::getMockLocation() {
+    V1_0::GnssLocation location = {.gnssLocationFlags = 0xFF,
+                                   .latitudeDegrees = 37.4219999,
+                                   .longitudeDegrees = -122.0840575,
+                                   .altitudeMeters = 1.60062531,
+                                   .speedMetersPerSec = 0,
+                                   .bearingDegrees = 0,
+                                   .horizontalAccuracyMeters = 5,
+                                   .verticalAccuracyMeters = 5,
+                                   .speedAccuracyMetersPerSecond = 1,
+                                   .bearingAccuracyDegrees = 90,
+                                   .timestamp = 1519930775453L};
+    return location;
+}
+
+Return<void> Gnss::reportLocation(const V1_0::GnssLocation& location) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (sGnssCallback == nullptr) {
+        ALOGE("%s: sGnssCallback is null.", __func__);
+        return Void();
+    }
+    sGnssCallback->gnssLocationCb(location);
+    return Void();
+}
 
 }  // namespace implementation
 }  // namespace V1_1
diff --git a/gnss/1.1/default/Gnss.h b/gnss/1.1/default/Gnss.h
index e9ad34b..68c3498 100644
--- a/gnss/1.1/default/Gnss.h
+++ b/gnss/1.1/default/Gnss.h
@@ -4,6 +4,9 @@
 #include <android/hardware/gnss/1.1/IGnss.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
 
 namespace android {
 namespace hardware {
@@ -19,7 +22,13 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
+/**
+ * Unlike the gnss/1.0/default implementation, which is a shim layer to the legacy gps.h, this
+ * default implementation serves as a mock implementation for emulators
+ */
 struct Gnss : public IGnss {
+    Gnss();
+    ~Gnss();
     // Methods from ::android::hardware::gnss::V1_0::IGnss follow.
     Return<bool> setCallback(
         const sp<::android::hardware::gnss::V1_0::IGnssCallback>& callback) override;
@@ -68,6 +77,15 @@
         const ::android::hardware::gnss::V1_0::GnssLocation& location) override;
 
     // Methods from ::android::hidl::base::V1_0::IBase follow.
+   private:
+    Return<V1_0::GnssLocation> getMockLocation();
+    Return<void> reportLocation(const V1_0::GnssLocation& location);
+
+    static sp<::android::hardware::gnss::V1_1::IGnssCallback> sGnssCallback;
+    std::atomic<bool> mIsActive;
+    std::thread mThread;
+    std::mutex mMutex;
+    std::atomic<long> mMinIntervalMs;
 };
 
 }  // namespace implementation
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp
index 23b7317..9c5ac2d 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "GnssHalTest"
+
 #include <gnss_hal_test.h>
 
 #include <chrono>
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index a0a1c73..63b6c78 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "GnssHalTestCases"
+
 #include <gnss_hal_test.h>
 
 #include <VtsHalHidlTargetTestBase.h>