Add IGnssPowerIndication AIDL HAL (hardware/interfaces)

Bug: 168123084
Bug: 171821213
Bug: 172893736
Test: on Cuttlefish
Change-Id: Ia9fd1981a6f93b2cad168bd52dae8d7b8ede0282
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
new file mode 100644
index 0000000..354c953
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+parcelable ElapsedRealtime {
+  int flags;
+  long timestampNs;
+  double timeUncertaintyNs;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
new file mode 100644
index 0000000..d385fd4
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+parcelable GnssPowerStats {
+  android.hardware.gnss.ElapsedRealtime elapsedRealtime;
+  double totalEnergyMilliJoule;
+  double singlebandTrackingModeEnergyMilliJoule;
+  double multibandTrackingModeEnergyMilliJoule;
+  double singlebandAcquisitionModeEnergyMilliJoule;
+  double multibandAcquisitionModeEnergyMilliJoule;
+  double[] otherModesEnergyMilliJoule;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index 146577e..e1a4b9e 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
@@ -22,5 +22,8 @@
   void close();
   android.hardware.gnss.IGnssPsds getExtensionPsds();
   android.hardware.gnss.IGnssConfiguration getExtensionGnssConfiguration();
+  android.hardware.gnss.IGnssPowerIndication getExtensionGnssPowerIndication();
   const int ERROR_INVALID_ARGUMENT = 1;
+  const int ELAPSED_REALTIME_HAS_TIMESTAMP_NS = 1;
+  const int ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS = 2;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
new file mode 100644
index 0000000..843489e
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IGnssPowerIndication {
+  void setCallback(in android.hardware.gnss.IGnssPowerIndicationCallback callback);
+  oneway void requestGnssPowerStats();
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
new file mode 100644
index 0000000..5281d29
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
@@ -0,0 +1,29 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IGnssPowerIndicationCallback {
+  void setCapabilitiesCb(in int capabilities);
+  oneway void gnssPowerStatsCb(in android.hardware.gnss.GnssPowerStats gnssPowerStats);
+  const int CAPABILITY_TOTAL = 1;
+  const int CAPABILITY_SINGLEBAND_TRACKING = 2;
+  const int CAPABILITY_MULTIBAND_TRACKING = 4;
+  const int CAPABILITY_SINGLEBAND_ACQUISITION = 8;
+  const int CAPABILITY_MULTIBAND_ACQUISITION = 16;
+  const int CAPABILITY_OTHER_MODES = 32;
+}
diff --git a/gnss/aidl/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/android/hardware/gnss/ElapsedRealtime.aidl
new file mode 100644
index 0000000..fae14f8
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/ElapsedRealtime.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss;
+
+/**
+ * Cumulative GNSS power statistics since boot.
+ */
+@VintfStability
+parcelable ElapsedRealtime {
+
+    /**
+     * A bit field of flags indicating the validity of each field in this data structure.
+     *
+     * The bit masks are defined in IGnss interface and prefixed with ELAPSED_REALTIME_HAS_.
+     *
+     * Fields may have invalid information in them, if not marked as valid by the corresponding bit
+     * in flags.
+     */
+    int flags;
+
+    /**
+     * Estimate of the elapsed time since boot value for the corresponding event in nanoseconds.
+     */
+    long timestampNs;
+
+    /**
+     * Estimate of the relative precision of the alignment of this SystemClock timestamp, with the
+     * reported measurements in nanoseconds (68% confidence).
+     */
+    double timeUncertaintyNs;
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/GnssPowerStats.aidl b/gnss/aidl/android/hardware/gnss/GnssPowerStats.aidl
new file mode 100644
index 0000000..2bea44d
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/GnssPowerStats.aidl
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.ElapsedRealtime;
+
+/**
+ * Cumulative GNSS power statistics since boot.
+ */
+@VintfStability
+parcelable GnssPowerStats {
+    /**
+     * Timing information of the GnssPowerStats synchronized with SystemClock.elapsedRealtimeNanos()
+     * clock.
+     */
+    ElapsedRealtime elapsedRealtime;
+
+    /**
+     * Total GNSS energy consumption in milli-joules (mWatt-seconds).
+     */
+    double totalEnergyMilliJoule;
+
+    /**
+     * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is
+     * tracking signals of a single frequency band.
+     */
+    double singlebandTrackingModeEnergyMilliJoule;
+
+    /**
+     * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is
+     * tracking signals of multiple frequency bands.
+     */
+    double multibandTrackingModeEnergyMilliJoule;
+
+    /**
+     * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is
+     * acquiring signals of a single frequency band.
+     */
+    double singlebandAcquisitionModeEnergyMilliJoule;
+
+    /**
+     * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is
+     * acquiring signals of multiple frequency bands.
+     */
+    double multibandAcquisitionModeEnergyMilliJoule;
+
+    /**
+     * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is
+     * operating in each of the vendor-specific power modes.
+     */
+    double[] otherModesEnergyMilliJoule;
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index 24632aa..2af57b5 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -17,6 +17,7 @@
 package android.hardware.gnss;
 
 import android.hardware.gnss.IGnssCallback;
+import android.hardware.gnss.IGnssPowerIndication;
 import android.hardware.gnss.IGnssPsds;
 import android.hardware.gnss.IGnssConfiguration;
 
@@ -32,6 +33,14 @@
      */
     const int ERROR_INVALID_ARGUMENT = 1;
 
+    /** Bit mask indicating a valid timestampNs is stored in the ElapsedRealtime parcelable. */
+    const int ELAPSED_REALTIME_HAS_TIMESTAMP_NS = 1 << 0;
+
+    /**
+     * Bit mask indicating a valid timeUncertaintyNs is stored in the ElapsedRealtime parcelable.
+     */
+    const int ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS = 1 << 1;
+
     /**
      * Opens the interface and provides the callback routines to the implementation of this
      * interface.
@@ -75,4 +84,11 @@
      * @return Handle to the IGnssConfiguration interface.
      */
     IGnssConfiguration getExtensionGnssConfiguration();
-}
\ No newline at end of file
+
+    /**
+     * This method returns the IGnssPowerIndication interface.
+     *
+     * @return Handle to the IGnssPowerIndication interface.
+     */
+    IGnssPowerIndication getExtensionGnssPowerIndication();
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssPowerIndication.aidl b/gnss/aidl/android/hardware/gnss/IGnssPowerIndication.aidl
new file mode 100644
index 0000000..93fdadc
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssPowerIndication.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.IGnssPowerIndicationCallback;
+
+/**
+ * Extended interface for GNSS Power Indication support.
+ */
+@VintfStability
+interface IGnssPowerIndication {
+
+    /**
+     * Opens the IGnssPowerIndication interface and provides the callback routines to the HAL.
+     *
+     * @param callback Callback interface for IGnssPowerIndication.
+     */
+    void setCallback(in IGnssPowerIndicationCallback callback);
+
+    /**
+     * Requests the GNSS power statistics. One request call corresponds to one response callback
+     * from IGnssPowerIndicationCallback.gnssPowerStatsCb().
+     */
+    oneway void requestGnssPowerStats();
+}
\ No newline at end of file
diff --git a/gnss/aidl/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
new file mode 100644
index 0000000..4474c0c
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.GnssPowerStats;
+
+/**
+ * The callback interface to report GNSS Power Indication from the HAL.
+ */
+@VintfStability
+interface IGnssPowerIndicationCallback {
+
+    /** Capability bit mask indicating GNSS supports totalEnergyMilliJoule. */
+    const int CAPABILITY_TOTAL = 1 << 0;
+
+    /** Capability bit mask indicating GNSS supports singlebandTrackingModeEnergyMilliJoule. */
+    const int CAPABILITY_SINGLEBAND_TRACKING = 1 << 1;
+
+    /** Capability bit mask indicating GNSS supports multibandTrackingModeEnergyMilliJoule. */
+    const int CAPABILITY_MULTIBAND_TRACKING = 1 << 2;
+
+    /** Capability bit mask indicating GNSS supports singlebandAcquisitionModeEnergyMilliJoule. */
+    const int CAPABILITY_SINGLEBAND_ACQUISITION = 1 << 3;
+
+    /** Capability bit mask indicating GNSS supports multibandAcquisitionModeEnergyMilliJoule. */
+    const int CAPABILITY_MULTIBAND_ACQUISITION = 1 << 4;
+
+    /** Capability bit mask indicating GNSS supports otherModesEnergyMilliJoule. */
+    const int CAPABILITY_OTHER_MODES = 1 << 5;
+
+    /**
+     * Callback to inform framework the Power Indication specific capabilities of the GNSS HAL
+     * implementation.
+     *
+     * The GNSS HAL must call this method immediately after the framework opens the
+     * IGnssPowerIndication interface.
+     *
+     * @param capabilities Bitmask of CAPABILITY_* specifying the supported GNSS Power Indication
+     * capabilities.
+     */
+    void setCapabilitiesCb(in int capabilities);
+
+    /**
+     * Callback for the HAL to pass a GnssPowerStats structure back to the client.
+     *
+     * @param gnssPowerStats GNSS power statistics since boot.
+     */
+    oneway void gnssPowerStatsCb(in GnssPowerStats gnssPowerStats);
+}
\ No newline at end of file
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index 1fe43c3..23677ed 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -47,6 +47,7 @@
     srcs: [
         "Gnss.cpp",
         "GnssHidlHal.cpp",
+        "GnssPowerIndication.cpp",
         "GnssPsds.cpp",
         "GnssConfiguration.cpp",
         "service.cpp",
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index b4d92fd..669372b 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -19,6 +19,7 @@
 #include "Gnss.h"
 #include <log/log.h>
 #include "GnssConfiguration.h"
+#include "GnssPowerIndication.h"
 #include "GnssPsds.h"
 
 namespace aidl::android::hardware::gnss {
@@ -65,4 +66,12 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Gnss::getExtensionGnssPowerIndication(
+        std::shared_ptr<IGnssPowerIndication>* iGnssPowerIndication) {
+    ALOGD("Gnss::getExtensionGnssPowerIndication");
+
+    *iGnssPowerIndication = SharedRefBase::make<GnssPowerIndication>();
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h
index 61d7cf7..9f6ef0e 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -18,6 +18,7 @@
 
 #include <aidl/android/hardware/gnss/BnGnss.h>
 #include <aidl/android/hardware/gnss/BnGnssConfiguration.h>
+#include <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
 #include <aidl/android/hardware/gnss/BnGnssPsds.h>
 #include "GnssConfiguration.h"
 
@@ -30,6 +31,8 @@
     ndk::ScopedAStatus getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) override;
     ndk::ScopedAStatus getExtensionGnssConfiguration(
             std::shared_ptr<IGnssConfiguration>* iGnssConfiguration) override;
+    ndk::ScopedAStatus getExtensionGnssPowerIndication(
+            std::shared_ptr<IGnssPowerIndication>* iGnssPowerIndication) override;
 
     std::shared_ptr<GnssConfiguration> mGnssConfiguration;
 
diff --git a/gnss/aidl/default/GnssPowerIndication.cpp b/gnss/aidl/default/GnssPowerIndication.cpp
new file mode 100644
index 0000000..8ea60f3
--- /dev/null
+++ b/gnss/aidl/default/GnssPowerIndication.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "GnssPowerIndicationAidl"
+
+#include "GnssPowerIndication.h"
+#include <aidl/android/hardware/gnss/BnGnss.h>
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss {
+
+std::shared_ptr<IGnssPowerIndicationCallback> GnssPowerIndication::sCallback = nullptr;
+
+ndk::ScopedAStatus GnssPowerIndication::setCallback(
+        const std::shared_ptr<IGnssPowerIndicationCallback>& callback) {
+    ALOGD("setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    sCallback->setCapabilitiesCb(IGnssPowerIndicationCallback::CAPABILITY_TOTAL |
+                                 IGnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_TRACKING |
+                                 IGnssPowerIndicationCallback::CAPABILITY_MULTIBAND_TRACKING |
+                                 IGnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_ACQUISITION |
+                                 IGnssPowerIndicationCallback::CAPABILITY_MULTIBAND_ACQUISITION |
+                                 IGnssPowerIndicationCallback::CAPABILITY_OTHER_MODES);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssPowerIndication::requestGnssPowerStats() {
+    ALOGD("requestGnssPowerStats");
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    ElapsedRealtime elapsedRealtime = {
+            .flags = IGnss::ELAPSED_REALTIME_HAS_TIMESTAMP_NS |
+                     IGnss::ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS,
+            .timestampNs = (long)1323542,
+            .timeUncertaintyNs = (long)1000,
+    };
+    GnssPowerStats gnssPowerStats = {
+            .elapsedRealtime = elapsedRealtime,
+            .totalEnergyMilliJoule = 1.59975e+3,
+            .singlebandTrackingModeEnergyMilliJoule = 1.2342e+3,
+            .multibandTrackingModeEnergyMilliJoule = 3.653e+2,
+            .otherModesEnergyMilliJoule = {1.232e+2, 3.234e+3},
+    };
+    sCallback->gnssPowerStatsCb(gnssPowerStats);
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssPowerIndication.h b/gnss/aidl/default/GnssPowerIndication.h
new file mode 100644
index 0000000..e32fd72
--- /dev/null
+++ b/gnss/aidl/default/GnssPowerIndication.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
+
+namespace aidl::android::hardware::gnss {
+
+struct GnssPowerIndication : public BnGnssPowerIndication {
+  public:
+    ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IGnssPowerIndicationCallback>& callback) override;
+    ndk::ScopedAStatus requestGnssPowerStats() override;
+
+  private:
+    // Guarded by mMutex
+    static std::shared_ptr<IGnssPowerIndicationCallback> sCallback;
+
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index 48a0e21..d102e7f 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -22,6 +22,7 @@
         "gnss_hal_test.cpp",
         "gnss_hal_test_cases.cpp",
         "GnssCallbackAidl.cpp",
+        "GnssPowerIndicationCallback.cpp",
         "VtsHalGnssTargetTest.cpp",
     ],
     shared_libs: [
diff --git a/gnss/aidl/vts/GnssPowerIndicationCallback.cpp b/gnss/aidl/vts/GnssPowerIndicationCallback.cpp
new file mode 100644
index 0000000..1cbfc20
--- /dev/null
+++ b/gnss/aidl/vts/GnssPowerIndicationCallback.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "GnssPwrIndCallback"
+
+#include "GnssPowerIndicationCallback.h"
+#include <log/log.h>
+
+using android::hardware::gnss::GnssPowerStats;
+
+android::binder::Status GnssPowerIndicationCallback::setCapabilitiesCb(const int capabilities) {
+    ALOGI("Capabilities received %d", capabilities);
+    capabilities_cbq_.store(capabilities);
+    return android::binder::Status::ok();
+}
+
+android::binder::Status GnssPowerIndicationCallback::gnssPowerStatsCb(
+        const GnssPowerStats& gnssPowerStats) {
+    ALOGI("gnssPowerStatsCb");
+    ALOGI("elapsedRealtime: %ld, totalEnergyMilliJoule: %f",
+          (long)gnssPowerStats.elapsedRealtime.timestampNs, gnssPowerStats.totalEnergyMilliJoule);
+    ALOGI("singlebandTrackingModeEnergyMilliJoule: %f, multibandTrackingModeEnergyMilliJoule: %f",
+          gnssPowerStats.singlebandTrackingModeEnergyMilliJoule,
+          gnssPowerStats.multibandTrackingModeEnergyMilliJoule);
+    ALOGI("singlebandAcquisitionModeEnergyMilliJoule: %f, "
+          "multibandAcquisitionModeEnergyMilliJoule: %f",
+          gnssPowerStats.singlebandAcquisitionModeEnergyMilliJoule,
+          gnssPowerStats.multibandAcquisitionModeEnergyMilliJoule);
+    for (const auto& otherModeEnergyMilliJoule : gnssPowerStats.otherModesEnergyMilliJoule) {
+        ALOGI("otherModeEnergyMilliJoule: %f", otherModeEnergyMilliJoule);
+    }
+    gnss_power_stats_cbq_.store(gnssPowerStats);
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/GnssPowerIndicationCallback.h b/gnss/aidl/vts/GnssPowerIndicationCallback.h
new file mode 100644
index 0000000..d4c4539
--- /dev/null
+++ b/gnss/aidl/vts/GnssPowerIndicationCallback.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/BnGnssPowerIndicationCallback.h>
+#include <android/hardware/gnss/GnssPowerStats.h>
+#include "GnssCallbackEventQueue.h"
+
+/** Implementation for IGnssPowerIndicationCallback. */
+class GnssPowerIndicationCallback : public android::hardware::gnss::BnGnssPowerIndicationCallback {
+  public:
+    GnssPowerIndicationCallback()
+        : capabilities_cbq_("capabilities"),
+          other_mode_names_cbq_("other_mode_names"),
+          gnss_power_stats_cbq_("gnss_power_stats") {}
+    ~GnssPowerIndicationCallback() {}
+
+    android::binder::Status setCapabilitiesCb(const int capabilities) override;
+    android::binder::Status gnssPowerStatsCb(
+            const android::hardware::gnss::GnssPowerStats& gnssPowerStats) override;
+
+    android::hardware::gnss::common::GnssCallbackEventQueue<int> capabilities_cbq_;
+    int last_capabilities_;
+    android::hardware::gnss::common::GnssCallbackEventQueue<std::vector<std::string>>
+            other_mode_names_cbq_;
+    std::vector<std::string> last_other_mode_names_;
+    android::hardware::gnss::common::GnssCallbackEventQueue<android::hardware::gnss::GnssPowerStats>
+            gnss_power_stats_cbq_;
+    android::hardware::gnss::GnssPowerStats last_gnss_power_stats_;
+};
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index d621053..4e8d0bd 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -16,13 +16,16 @@
 
 #define LOG_TAG "GnssHalTestCases"
 
+#include <android/hardware/gnss/IGnssPowerIndication.h>
 #include <android/hardware/gnss/IGnssPsds.h>
+#include "GnssPowerIndicationCallback.h"
 #include "gnss_hal_test.h"
 
 using android::sp;
 using android::hardware::gnss::BlocklistedSource;
 using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType;
 using android::hardware::gnss::IGnssConfiguration;
+using android::hardware::gnss::IGnssPowerIndication;
 using android::hardware::gnss::IGnssPsds;
 using android::hardware::gnss::PsdsType;
 
@@ -37,7 +40,7 @@
 /*
  * TestPsdsExtension:
  * 1. Gets the PsdsExtension and verifies that it returns a non-null extension.
- * 2. Injects empty PSDS data and verifies that it returns false.
+ * 2. Injects empty PSDS data and verifies that it returns an error.
  */
 TEST_P(GnssHalTest, TestPsdsExtension) {
     sp<IGnssPsds> iGnssPsds;
@@ -50,6 +53,34 @@
 }
 
 /*
+ * TestGnssPowerIndication
+ * 1. Gets the GnssPowerIndicationExtension.
+ * 2. Sets a GnssPowerIndicationCallback.
+ * 3.
+ */
+TEST_P(GnssHalTest, TestGnssPowerIndication) {
+    sp<IGnssPowerIndication> iGnssPowerIndication;
+    auto status = aidl_gnss_hal_->getExtensionGnssPowerIndication(&iGnssPowerIndication);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(iGnssPowerIndication != nullptr);
+
+    auto gnssPowerIndicationCallback = sp<GnssPowerIndicationCallback>::make();
+    status = iGnssPowerIndication->setCallback(gnssPowerIndicationCallback);
+    ASSERT_TRUE(status.isOk());
+
+    const int kTimeoutSec = 2;
+    EXPECT_TRUE(gnssPowerIndicationCallback->capabilities_cbq_.retrieve(
+            gnssPowerIndicationCallback->last_capabilities_, kTimeoutSec));
+
+    EXPECT_EQ(gnssPowerIndicationCallback->capabilities_cbq_.calledCount(), 1);
+
+    iGnssPowerIndication->requestGnssPowerStats();
+    EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve(
+            gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec));
+    EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 1);
+}
+
+/*
  * FindStrongFrequentNonGpsSource:
  *
  * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times