summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Siddharth Ray <siddharthr@google.com> 2018-01-19 21:40:07 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-01-19 21:40:07 +0000
commitf87fe4845608d26da0a7d5b5dc07c6d3cb3c7ff4 (patch)
tree1bc4c399b5fabcc20e105d25c8cf272f1d822873
parent19916d8b8edbf26e49bedfbd805bc3772af02576 (diff)
parent78ccaf5d287cbb6bd214913d72653aa74ecfef76 (diff)
Merge "GPS Signal Quality added to BatteryStats"
-rw-r--r--core/java/android/os/BatteryStats.java62
-rw-r--r--core/java/android/os/connectivity/GpsBatteryStats.aidl20
-rw-r--r--core/java/android/os/connectivity/GpsBatteryStats.java108
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl5
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java99
-rw-r--r--location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java86
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java17
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java2
8 files changed, 395 insertions, 4 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4c35a5c75c47..49879a8a84a7 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -35,6 +35,7 @@ import android.util.proto.ProtoOutputStream;
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.location.gnssmetrics.GnssMetrics;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
@@ -1508,6 +1509,10 @@ public abstract class BatteryStats implements Parcelable {
public static final int STATE2_WIFI_SIGNAL_STRENGTH_SHIFT = 4;
public static final int STATE2_WIFI_SIGNAL_STRENGTH_MASK =
0x7 << STATE2_WIFI_SIGNAL_STRENGTH_SHIFT;
+ // Values for NUM_GPS_SIGNAL_QUALITY_LEVELS
+ public static final int STATE2_GPS_SIGNAL_QUALITY_SHIFT = 7;
+ public static final int STATE2_GPS_SIGNAL_QUALITY_MASK =
+ 0x1 << STATE2_GPS_SIGNAL_QUALITY_SHIFT;
public static final int STATE2_POWER_SAVE_FLAG = 1<<31;
public static final int STATE2_VIDEO_ON_FLAG = 1<<30;
@@ -2096,6 +2101,23 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract int getNumConnectivityChange(int which);
+
+ /**
+ * Returns the time in microseconds that the phone has been running with
+ * the given GPS signal quality level
+ *
+ * {@hide}
+ */
+ public abstract long getGpsSignalQualityTime(int strengthBin,
+ long elapsedRealtimeUs, int which);
+
+ /**
+ * Returns the GPS battery drain in mA-ms
+ *
+ * {@hide}
+ */
+ public abstract long getGpsBatteryDrainMaMs();
+
/**
* Returns the time in microseconds that the phone has been on while the device was
* running on battery.
@@ -2320,6 +2342,9 @@ public abstract class BatteryStats implements Parcelable {
WIFI_SUPPL_STATE_NAMES, WIFI_SUPPL_STATE_SHORT_NAMES),
new BitDescription(HistoryItem.STATE2_CAMERA_FLAG, "camera", "ca"),
new BitDescription(HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG, "ble_scan", "bles"),
+ new BitDescription(HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK,
+ HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT, "gps_signal_quality", "Gss",
+ new String[] { "poor", "good"}, new String[] { "poor", "good"}),
};
public static final String[] HISTORY_EVENT_NAMES = new String[] {
@@ -4740,6 +4765,43 @@ public abstract class BatteryStats implements Parcelable {
pw.print(prefix);
sb.setLength(0);
sb.append(prefix);
+ sb.append(" GPS Statistics:");
+ pw.println(sb.toString());
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" GPS signal quality (Top 4 Average CN0):");
+ final String[] gpsSignalQualityDescription = new String[]{
+ "poor (less than 20 dBHz): ",
+ "good (greater than 20 dBHz): "};
+ final int numGpsSignalQualityBins = Math.min(GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS,
+ gpsSignalQualityDescription.length);
+ for (int i=0; i<numGpsSignalQualityBins; i++) {
+ final long time = getGpsSignalQualityTime(i, rawRealtime, which);
+ sb.append("\n ");
+ sb.append(prefix);
+ sb.append(" ");
+ sb.append(gpsSignalQualityDescription[i]);
+ formatTimeMs(sb, time/1000);
+ sb.append("(");
+ sb.append(formatRatioLocked(time, whichBatteryRealtime));
+ sb.append(") ");
+ }
+ pw.println(sb.toString());
+
+ final long gpsBatteryDrainMaMs = getGpsBatteryDrainMaMs();
+ if (gpsBatteryDrainMaMs > 0) {
+ pw.print(prefix);
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Battery Drain (mAh): ");
+ sb.append(Double.toString(((double) gpsBatteryDrainMaMs)/(3600 * 1000)));
+ pw.println(sb.toString());
+ }
+
+ pw.print(prefix);
+ sb.setLength(0);
+ sb.append(prefix);
sb.append(" CONNECTIVITY POWER SUMMARY END");
pw.println(sb.toString());
pw.println("");
diff --git a/core/java/android/os/connectivity/GpsBatteryStats.aidl b/core/java/android/os/connectivity/GpsBatteryStats.aidl
new file mode 100644
index 000000000000..7b96d1a8e062
--- /dev/null
+++ b/core/java/android/os/connectivity/GpsBatteryStats.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 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.os.connectivity;
+
+/** {@hide} */
+parcelable GpsBatteryStats; \ No newline at end of file
diff --git a/core/java/android/os/connectivity/GpsBatteryStats.java b/core/java/android/os/connectivity/GpsBatteryStats.java
new file mode 100644
index 000000000000..f2ac5ef6d40b
--- /dev/null
+++ b/core/java/android/os/connectivity/GpsBatteryStats.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 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.os.connectivity;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.location.gnssmetrics.GnssMetrics;
+
+import java.util.Arrays;
+
+/**
+ * API for GPS power stats
+ *
+ * @hide
+ */
+public final class GpsBatteryStats implements Parcelable {
+
+ private long mLoggingDurationMs;
+ private long mEnergyConsumedMaMs;
+ private long[] mTimeInGpsSignalQualityLevel;
+
+ public static final Parcelable.Creator<GpsBatteryStats> CREATOR = new
+ Parcelable.Creator<GpsBatteryStats>() {
+ public GpsBatteryStats createFromParcel(Parcel in) {
+ return new GpsBatteryStats(in);
+ }
+
+ public GpsBatteryStats[] newArray(int size) {
+ return new GpsBatteryStats[size];
+ }
+ };
+
+ public GpsBatteryStats() {
+ initialize();
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeLong(mLoggingDurationMs);
+ out.writeLong(mEnergyConsumedMaMs);
+ out.writeLongArray(mTimeInGpsSignalQualityLevel);
+ }
+
+ public void readFromParcel(Parcel in) {
+ mLoggingDurationMs = in.readLong();
+ mEnergyConsumedMaMs = in.readLong();
+ in.readLongArray(mTimeInGpsSignalQualityLevel);
+ }
+
+ public long getLoggingDurationMs() {
+ return mLoggingDurationMs;
+ }
+
+ public long getEnergyConsumedMaMs() {
+ return mEnergyConsumedMaMs;
+ }
+
+ public long[] getTimeInGpsSignalQualityLevel() {
+ return mTimeInGpsSignalQualityLevel;
+ }
+
+ public void setLoggingDurationMs(long t) {
+ mLoggingDurationMs = t;
+ return;
+ }
+
+ public void setEnergyConsumedMaMs(long e) {
+ mEnergyConsumedMaMs = e;
+ return;
+ }
+
+ public void setTimeInGpsSignalQualityLevel(long[] t) {
+ mTimeInGpsSignalQualityLevel = Arrays.copyOfRange(t, 0,
+ Math.min(t.length, GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS));
+ return;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private GpsBatteryStats(Parcel in) {
+ initialize();
+ readFromParcel(in);
+ }
+
+ private void initialize() {
+ mLoggingDurationMs = 0;
+ mEnergyConsumedMaMs = 0;
+ mTimeInGpsSignalQualityLevel = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+ return;
+ }
+} \ No newline at end of file
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 388180dc61e0..e2d1ad59043e 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -23,6 +23,7 @@ import android.net.wifi.WifiActivityEnergyInfo;
import android.os.ParcelFileDescriptor;
import android.os.WorkSource;
import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
import android.os.health.HealthStatsParceler;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.ModemActivityInfo;
@@ -91,6 +92,7 @@ interface IBatteryStats {
void noteVibratorOff(int uid);
void noteStartGps(int uid);
void noteStopGps(int uid);
+ void noteGpsSignalQuality(int signalLevel);
void noteScreenState(int state);
void noteScreenBrightness(int brightness);
void noteUserActivity(int uid, int event);
@@ -140,6 +142,9 @@ interface IBatteryStats {
/** {@hide} */
CellularBatteryStats getCellularBatteryStats();
+ /** {@hide} */
+ GpsBatteryStats getGpsBatteryStats();
+
HealthStatsParceler takeUidSnapshot(int uid);
HealthStatsParceler[] takeUidSnapshots(in int[] uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b4bfee5802ff..bd22b33f9507 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -34,6 +34,7 @@ import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Build;
import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBatteryPropertiesRegistrar;
@@ -78,6 +79,7 @@ import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.location.gnssmetrics.GnssMetrics;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
@@ -672,6 +674,10 @@ public class BatteryStatsImpl extends BatteryStats {
int mCameraOnNesting;
StopwatchTimer mCameraOnTimer;
+ int mGpsSignalQualityBin = -1;
+ final StopwatchTimer[] mGpsSignalQualityTimer =
+ new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+
int mPhoneSignalStrengthBin = -1;
int mPhoneSignalStrengthBinRaw = -1;
final StopwatchTimer[] mPhoneSignalStrengthsTimer =
@@ -4583,10 +4589,37 @@ public class BatteryStatsImpl extends BatteryStats {
if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(elapsedRealtime, uptime);
+ stopAllGpsSignalQualityTimersLocked(-1);
+ mGpsSignalQualityBin = -1;
}
getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
}
+ public void noteGpsSignalQualityLocked(int signalLevel) {
+ if (mGpsNesting == 0) {
+ return;
+ }
+ if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+ stopAllGpsSignalQualityTimersLocked(-1);
+ return;
+ }
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
+ if (mGpsSignalQualityBin != signalLevel) {
+ if (mGpsSignalQualityBin >= 0) {
+ mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
+ }
+ if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
+ mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
+ }
+ mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
+ | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
+ addHistoryRecordLocked(elapsedRealtime, uptime);
+ mGpsSignalQualityBin = signalLevel;
+ }
+ return;
+ }
+
public void noteScreenStateLocked(int state) {
state = mPretendScreenOff ? Display.STATE_OFF : state;
@@ -4920,6 +4953,18 @@ public class BatteryStatsImpl extends BatteryStats {
mDailyPackageChanges.add(pc);
}
+ void stopAllGpsSignalQualityTimersLocked(int except) {
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ if (i == except) {
+ continue;
+ }
+ while (mGpsSignalQualityTimer[i].isRunningLocked()) {
+ mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
+ }
+ }
+ }
+
public void notePhoneOnLocked() {
if (!mPhoneOn) {
final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -6131,6 +6176,20 @@ public class BatteryStatsImpl extends BatteryStats {
return val;
}
+ @Override public long getGpsSignalQualityTime(int strengthBin,
+ long elapsedRealtimeUs, int which) {
+ if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+ return 0;
+ }
+ return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
+ elapsedRealtimeUs, which);
+ }
+
+ @Override public long getGpsBatteryDrainMaMs() {
+ //TODO: Add GPS power computation (b/67213967)
+ return 0;
+ }
+
@Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
}
@@ -9857,6 +9916,10 @@ public class BatteryStatsImpl extends BatteryStats {
mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
mOnBatteryTimeBase);
}
+ for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
+ mOnBatteryTimeBase);
+ }
mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
@@ -10546,6 +10609,9 @@ public class BatteryStatsImpl extends BatteryStats {
mWifiSignalStrengthsTimer[i].reset(false);
}
mWifiMulticastWakelockTimer.reset(false);
+ for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ mGpsSignalQualityTimer[i].reset(false);
+ }
mWifiActivity.reset(false);
mBluetoothActivity.reset(false);
mModemActivity.reset(false);
@@ -12464,6 +12530,21 @@ public class BatteryStatsImpl extends BatteryStats {
return s;
}
+ /*@hide */
+ public GpsBatteryStats getGpsBatteryStats() {
+ GpsBatteryStats s = new GpsBatteryStats();
+ final int which = STATS_SINCE_CHARGED;
+ final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
+ s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
+ s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
+ long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+ for (int i=0; i<time.length; i++) {
+ time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
+ }
+ s.setTimeInGpsSignalQualityLevel(time);
+ return s;
+ }
+
@Override
public LevelStepTracker getChargeLevelStepTracker() {
return mChargeStepTracker;
@@ -13141,6 +13222,9 @@ public class BatteryStatsImpl extends BatteryStats {
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
}
+ for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
+ }
mWifiActivity.readSummaryFromParcel(in);
mBluetoothActivity.readSummaryFromParcel(in);
mModemActivity.readSummaryFromParcel(in);
@@ -13583,6 +13667,9 @@ public class BatteryStatsImpl extends BatteryStats {
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
}
+ for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+ }
mWifiActivity.writeSummaryToParcel(out);
mBluetoothActivity.writeSummaryToParcel(out);
mModemActivity.writeSummaryToParcel(out);
@@ -14058,7 +14145,10 @@ public class BatteryStatsImpl extends BatteryStats {
mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
null, mOnBatteryTimeBase, in);
}
-
+ for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
+ null, mOnBatteryTimeBase, in);
+ }
mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
NUM_WIFI_TX_LEVELS, in);
mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
@@ -14258,6 +14348,9 @@ public class BatteryStatsImpl extends BatteryStats {
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
}
+ for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
+ }
mWifiActivity.writeToParcel(out, 0);
mBluetoothActivity.writeToParcel(out, 0);
mModemActivity.writeToParcel(out, 0);
@@ -14452,6 +14545,10 @@ public class BatteryStatsImpl extends BatteryStats {
pr.println("*** Wifi signal strength #" + i + ":");
mWifiSignalStrengthsTimer[i].logState(pr, " ");
}
+ for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ pr.println("*** GPS signal quality #" + i + ":");
+ mGpsSignalQualityTimer[i].logState(pr, " ");
+ }
pr.println("*** Flashlight timer:");
mFlashlightOnTimer.logState(pr, " ");
pr.println("*** Camera timer:");
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 833376cfa057..603926f4fe4d 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -19,10 +19,12 @@ package com.android.internal.location.gnssmetrics;
import android.os.SystemClock;
import android.util.Base64;
+import android.util.Log;
import android.util.TimeUtils;
import java.util.Arrays;
+import com.android.internal.app.IBatteryStats;
import com.android.internal.location.nano.GnssLogsProto.GnssLog;
/**
@@ -31,14 +33,29 @@ import com.android.internal.location.nano.GnssLogsProto.GnssLog;
*/
public class GnssMetrics {
+ private static final String TAG = GnssMetrics.class.getSimpleName();
+
+ /* Constant which indicates GPS signal quality is poor */
+ public static final int GPS_SIGNAL_QUALITY_POOR = 0;
+
+ /* Constant which indicates GPS signal quality is good */
+ public static final int GPS_SIGNAL_QUALITY_GOOD = 1;
+
+ /* Number of GPS signal quality levels */
+ public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
+
/** Default time between location fixes (in millisecs) */
private static final int DEFAULT_TIME_BETWEEN_FIXES_MILLISECS = 1000;
/* The time since boot when logging started */
private String logStartInElapsedRealTime;
+ /* GNSS power metrics */
+ private GnssPowerMetrics mGnssPowerMetrics;
+
/** Constructor */
- public GnssMetrics() {
+ public GnssMetrics(IBatteryStats stats) {
+ mGnssPowerMetrics = new GnssPowerMetrics(stats);
locationFailureStatistics = new Statistics();
timeToFirstFixSecStatistics = new Statistics();
positionAccuracyMeterStatistics = new Statistics();
@@ -103,11 +120,18 @@ public class GnssMetrics {
*
*/
public void logCn0(float[] cn0s, int numSv) {
- if (numSv < 4) {
+ if (numSv == 0 || cn0s == null || cn0s.length == 0 || cn0s.length < numSv) {
+ if (numSv == 0) {
+ mGnssPowerMetrics.reportSignalQuality(null, 0);
+ }
return;
}
float[] cn0Array = Arrays.copyOf(cn0s, numSv);
Arrays.sort(cn0Array);
+ mGnssPowerMetrics.reportSignalQuality(cn0Array, numSv);
+ if (numSv < 4) {
+ return;
+ }
if (cn0Array[numSv - 4] > 0.0) {
double top4AvgCn0 = 0.0;
for (int i = numSv - 4; i < numSv; i++) {
@@ -265,4 +289,62 @@ public class GnssMetrics {
topFourAverageCn0Statistics.reset();
return;
}
+
+ /* Class for handling GNSS power related metrics */
+ private class GnssPowerMetrics {
+
+ /* Threshold for Top Four Average CN0 below which GNSS signal quality is declared poor */
+ private static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0;
+
+ /* Minimum change in Top Four Average CN0 needed to trigger a report */
+ private static final double REPORTING_THRESHOLD_DB_HZ = 1.0;
+
+ /* BatteryStats API */
+ private final IBatteryStats mBatteryStats;
+
+ /* Last reported Top Four Average CN0 */
+ private double mLastAverageCn0;
+
+ public GnssPowerMetrics(IBatteryStats stats) {
+ mBatteryStats = stats;
+ // Used to initialize the variable to a very small value (unachievable in practice) so that
+ // the first CNO report will trigger an update to BatteryStats
+ mLastAverageCn0 = -100.0;
+ }
+
+ /**
+ * Reports signal quality to BatteryStats. Signal quality is based on Top four average CN0. If
+ * the number of SVs seen is less than 4, then signal quality is the average CN0.
+ * Changes are reported only if the average CN0 changes by more than REPORTING_THRESHOLD_DB_HZ.
+ */
+ public void reportSignalQuality(float[] ascendingCN0Array, int numSv) {
+ double avgCn0 = 0.0;
+ if (numSv > 0) {
+ for (int i = Math.max(0, numSv - 4); i < numSv; i++) {
+ avgCn0 += (double) ascendingCN0Array[i];
+ }
+ avgCn0 /= Math.min(numSv, 4);
+ }
+ if (Math.abs(avgCn0 - mLastAverageCn0) < REPORTING_THRESHOLD_DB_HZ) {
+ return;
+ }
+ try {
+ mBatteryStats.noteGpsSignalQuality(getSignalLevel(avgCn0));
+ mLastAverageCn0 = avgCn0;
+ } catch (Exception e) {
+ Log.w(TAG, "Exception", e);
+ }
+ return;
+ }
+
+ /**
+ * Obtains signal level based on CN0
+ */
+ private int getSignalLevel(double cn0) {
+ if (cn0 > POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) {
+ return GnssMetrics.GPS_SIGNAL_QUALITY_GOOD;
+ }
+ return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
+ }
+ }
} \ No newline at end of file
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 81e8eb0d4136..207aaa76e5b8 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -40,6 +40,7 @@ import android.os.UserManagerInternal;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
import android.os.health.HealthStatsParceler;
import android.os.health.HealthStatsWriter;
import android.os.health.UidHealthStats;
@@ -594,6 +595,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ public void noteGpsSignalQuality(int signalLevel) {
+ synchronized (mStats) {
+ mStats.noteGpsSignalQualityLocked(signalLevel);
+ }
+ }
+
public void noteScreenState(int state) {
enforceCallingPermission();
if (DBG) Slog.d(TAG, "begin noteScreenState");
@@ -1448,6 +1455,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
/**
+ * Gets a snapshot of Gps stats
+ * @hide
+ */
+ public GpsBatteryStats getGpsBatteryStats() {
+ synchronized (mStats) {
+ return mStats.getGpsBatteryStats();
+ }
+ }
+
+ /**
* Gets a snapshot of the system health for a particular uid.
*/
@Override
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 6dc5403acc99..48d275cc483f 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -827,7 +827,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
return isEnabled();
}
};
- mGnssMetrics = new GnssMetrics();
+ mGnssMetrics = new GnssMetrics(mBatteryStats);
}
/**