am b02ad5ee: am d116ad43: resolved conflicts for merge of dae1c7c7 to jb-mr1-dev
* commit 'b02ad5ee6a4c27c5d1b30c11d52eb7153c8198a5':
Assert mean and stdev of update deltas
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/location/GpsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/location/GpsTestActivity.java
index 31b5854..bb12b2b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/location/GpsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/location/GpsTestActivity.java
@@ -95,25 +95,25 @@
case 1:
// Test GPS with minTime = 0
mLocationVerifier = new LocationVerifier(this, mLocationManager,
- LocationManager.GPS_PROVIDER, 0, 10);
+ LocationManager.GPS_PROVIDER, 0, 8);
mLocationVerifier.start();
break;
case 2:
// Test GPS with minTime = 1s
mLocationVerifier = new LocationVerifier(this, mLocationManager,
- LocationManager.GPS_PROVIDER, 1000, 10);
+ LocationManager.GPS_PROVIDER, 1 * 1000, 8);
mLocationVerifier.start();
break;
case 3:
// Test GPS with minTime = 5s
mLocationVerifier = new LocationVerifier(this, mLocationManager,
- LocationManager.GPS_PROVIDER, 5 * 1000, 4);
+ LocationManager.GPS_PROVIDER, 5 * 1000, 8);
mLocationVerifier.start();
break;
case 4:
// Test GPS with minTime = 15s
mLocationVerifier = new LocationVerifier(this, mLocationManager,
- LocationManager.GPS_PROVIDER, 15 * 1000, 4);
+ LocationManager.GPS_PROVIDER, 15 * 1000, 8);
mLocationVerifier.start();
break;
case 5:
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/location/LocationVerifier.java b/apps/CtsVerifier/src/com/android/cts/verifier/location/LocationVerifier.java
index 143ee24..b6d2a9e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/location/LocationVerifier.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/location/LocationVerifier.java
@@ -23,7 +23,11 @@
import android.os.Handler;
import android.os.Message;
+import java.util.List;
+import java.util.ArrayList;
+
public class LocationVerifier implements Handler.Callback {
+
public static final String TAG = "CtsVerifierLocation";
private static final int MSG_TIMEOUT = 1;
@@ -31,18 +35,29 @@
/** Timing failures on first NUM_IGNORED_UPDATES updates are ignored. */
private static final int NUM_IGNORED_UPDATES = 2;
+ /* The mean computed for the deltas should not be smaller
+ * than mInterval * MIN_MEAN_RATIO */
+ private static final double MIN_MEAN_RATIO = 0.75;
+
+ /**
+ * The standard deviation computed for the deltas should not be bigger
+ * than mInterval * ALLOWED_STDEV_ERROR_RATIO
+ * or MIN_STDEV_MS, whichever is higher.
+ */
+ private static final double ALLOWED_STDEV_ERROR_RATIO = 0.50;
+ private static final long MIN_STDEV_MS = 1000;
+
private final LocationManager mLocationManager;
private final PassFailLog mCb;
private final String mProvider;
private final long mInterval;
- private final long mMinActiveInterval;
- private final long mMinPassiveInterval;
private final long mTimeout;
private final Handler mHandler;
private final int mRequestedUpdates;
private final ActiveListener mActiveListener;
private final PassiveListener mPassiveListener;
+ private boolean isTestOutcomeSet = false;
private long mLastActiveTimestamp = -1;
private long mLastPassiveTimestamp = -1;
private int mNumActiveUpdates = 0;
@@ -50,6 +65,9 @@
private boolean mRunning = false;
private boolean mActiveLocationArrive = false;
+ private List<Long> mActiveDeltas = new ArrayList();
+ private List<Long> mPassiveDeltas = new ArrayList();
+
private class ActiveListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
@@ -63,38 +81,17 @@
long delta = timestamp - mLastActiveTimestamp;
mLastActiveTimestamp = timestamp;
- if (location.getAccuracy() <= 0.0) {
- fail(mProvider + " location has invalid accuracy: " + location.getAccuracy());
- }
- if (location.getElapsedRealtimeNanos() <= 0) {
- fail(mProvider + " location has invalid elapsed realtime: " +
- location.getElapsedRealtimeNanos());
- }
-
- if (delta < mMinActiveInterval) {
- if (mNumActiveUpdates > NUM_IGNORED_UPDATES ) {
- fail(mProvider + " location updated too fast: " + delta + "ms < " +
- mMinActiveInterval + "ms");
- return;
- } else {
- mCb.log("WARNING: active " + mProvider + " location updated too fast: " +
- delta + "ms < " + mMinActiveInterval + "ms");
- }
- }
-
- mCb.log("active " + mProvider + " update (" + delta + "ms)");
-
- if (!mProvider.equals(location.getProvider())) {
- fail("wrong provider in callback, actual: " + location.getProvider() +
- " expected: " + mProvider);
+ if (mNumActiveUpdates <= NUM_IGNORED_UPDATES ) {
+ mCb.log("(ignored) active " + mProvider + " update (" + delta + "ms)");
return;
}
+ mActiveDeltas.add(delta);
+ mCb.log("active " + mProvider + " update (" + delta + "ms)");
+
if (mNumActiveUpdates >= mRequestedUpdates) {
- if (mNumPassiveUpdates < mRequestedUpdates - 1) {
- fail("passive location updates not working (expected: " + mRequestedUpdates +
- " received: " + mNumPassiveUpdates + ")");
- }
+ assertMeanAndStdev(mProvider, mActiveDeltas);
+ assertMeanAndStdev(LocationManager.PASSIVE_PROVIDER, mPassiveDeltas);
pass();
}
}
@@ -107,6 +104,45 @@
public void onProviderDisabled(String provider) { }
}
+ private void assertMeanAndStdev(String provider, List<Long> deltas) {
+ double mean = computeMean(deltas);
+ double stdev = computeStdev(mean, deltas);
+
+ double minMean = mInterval * MIN_MEAN_RATIO;
+ if (mean < minMean) {
+ fail(provider + " provider mean too small: " + mean
+ + " (min: " + minMean + ")");
+ return;
+ }
+
+ double maxStdev = Math.max(MIN_STDEV_MS, mInterval * ALLOWED_STDEV_ERROR_RATIO);
+ if (stdev > maxStdev) {
+ fail (provider + " provider stdev too big: "
+ + stdev + " (max: " + maxStdev + ")");
+ return;
+ }
+
+ mCb.log(provider + " provider mean: " + mean);
+ mCb.log(provider + " provider stdev: " + stdev);
+ }
+
+ private double computeMean(List<Long> deltas) {
+ long accumulator = 0;
+ for (long d : deltas) {
+ accumulator += d;
+ }
+ return accumulator / deltas.size();
+ }
+
+ private double computeStdev(double mean, List<Long> deltas) {
+ double accumulator = 0;
+ for (long d : deltas) {
+ double diff = d - mean;
+ accumulator += diff * diff;
+ }
+ return Math.sqrt(accumulator / (deltas.size() - 1));
+ }
+
private class PassiveListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
@@ -127,30 +163,12 @@
long delta = timestamp - mLastPassiveTimestamp;
mLastPassiveTimestamp = timestamp;
- if (location.getAccuracy() <= 0.0) {
- fail(mProvider + " location has invalid accuracy: " + location.getAccuracy());
- }
- if (location.getElapsedRealtimeNanos() <= 0) {
- fail(mProvider + " location has invalid elapsed realtime: " +
- location.getElapsedRealtimeNanos());
+ if (mNumPassiveUpdates <= NUM_IGNORED_UPDATES) {
+ mCb.log("(ignored) passive " + mProvider + " update (" + delta + "ms)");
+ return;
}
- if (delta < mMinPassiveInterval) {
- if (mNumPassiveUpdates > NUM_IGNORED_UPDATES) {
- fail("passive " + mProvider + " location updated too fast: " + delta + "ms < " +
- mMinPassiveInterval + "ms");
- mCb.log("when passive updates are much much faster than active updates it " +
- "suggests the location provider implementation is not power efficient");
- if (LocationManager.GPS_PROVIDER.equals(mProvider)) {
- mCb.log("check GPS_CAPABILITY_SCHEDULING in GPS driver");
- }
- return;
- } else {
- mCb.log("WARNING: passive " + mProvider + " location updated too fast: " +
- delta + "ms < " + mMinPassiveInterval + "ms");
- }
- }
-
+ mPassiveDeltas.add(delta);
mCb.log("passive " + mProvider + " update (" + delta + "ms)");
}
@@ -166,12 +184,6 @@
String provider, long requestedInterval, int numUpdates) {
mProvider = provider;
mInterval = requestedInterval;
- // Updates can be up to 15% of the request interval ahead of schedule
- mMinActiveInterval = Math.max(0, (long) (requestedInterval * 0.85));
- // Allow passive updates to be up to 10x faster than active updates,
- // beyond that it is very likely the implementation is not taking
- // advantage of the interval to be power efficient
- mMinPassiveInterval = mMinActiveInterval / 10;
// timeout at 60 seconds after interval time
mTimeout = requestedInterval + 60 * 1000;
mRequestedUpdates = numUpdates + NUM_IGNORED_UPDATES;
@@ -205,13 +217,19 @@
}
private void pass() {
- stop();
- mCb.pass();
+ if (!isTestOutcomeSet) {
+ stop();
+ mCb.pass();
+ isTestOutcomeSet = true;
+ }
}
private void fail(String s) {
- stop();
- mCb.fail(s);
+ if (!isTestOutcomeSet) {
+ stop();
+ mCb.fail(s);
+ isTestOutcomeSet = true;
+ }
}
private void scheduleTimeout() {