summaryrefslogtreecommitdiffstats
path: root/location/tests/locationtests/src/android
diff options
context:
space:
mode:
authordestradaa <destradaa@google.com>2015-01-30 16:11:20 -0800
committerdestradaa <destradaa@google.com>2015-02-03 13:17:14 -0800
commit6bde4683ae1f70f7b5e53f853b6a7479bcebd5d5 (patch)
tree3804ff0a8b55fff0a506d7f5b2328c0e355d68ba /location/tests/locationtests/src/android
parentad575295918dba197dcf61bfb81d56348ed1f073 (diff)
downloadframeworks_base-6bde4683ae1f70f7b5e53f853b6a7479bcebd5d5.zip
frameworks_base-6bde4683ae1f70f7b5e53f853b6a7479bcebd5d5.tar.gz
frameworks_base-6bde4683ae1f70f7b5e53f853b6a7479bcebd5d5.tar.bz2
Reduce memory usage of GpsStatus objects.
A simple GpsStatus object uses 9K of space, given that it initializes an array of 255 GpsSatellite objects. This change reduces the memory footprint in the average case, and keeps the semantics of the API and its GpsSatellite sibling objects without any changes. In a best case scenario it brings the memory usage per object to 1K. It's likely in most cases that only 20-50 satellites will be in view. So the usage should not exceeed half of the original memory usage. It was considered to keep the internal array but a SparseArray provided bigger memory savings in the test scenario of ~700B. Change-Id: Ie2d2144d776a74d4904a08c0d6c5aec6d3bba7cc
Diffstat (limited to 'location/tests/locationtests/src/android')
-rw-r--r--location/tests/locationtests/src/android/location/GpsStatusTest.java356
1 files changed, 356 insertions, 0 deletions
diff --git a/location/tests/locationtests/src/android/location/GpsStatusTest.java b/location/tests/locationtests/src/android/location/GpsStatusTest.java
new file mode 100644
index 0000000..4808faf
--- /dev/null
+++ b/location/tests/locationtests/src/android/location/GpsStatusTest.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2015 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.location;
+
+import junit.framework.TestCase;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * Unit tests for {@link GpsStatus}.
+ */
+@SmallTest
+public class GpsStatusTest extends TestCase {
+
+ private static final int MAX_VALUE = 250;
+
+ private final Random mRandom = new Random();
+
+ private GpsStatus mStatus;
+ private int mCount;
+ private int[] mPrns;
+ private float[] mSnrs;
+ private float[] mElevations;
+ private float[] mAzimuth;
+ private int mEphemerisMask;
+ private int mAlmanacMask;
+ private int mUsedInFixMask;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ mStatus = createGpsStatus();
+ generateSatellitesData(generateInt());
+ }
+
+ public void testEmptyGpsStatus() throws Exception {
+ verifyIsEmpty(mStatus);
+ }
+
+ public void testGpsStatusIterator() throws Exception {
+ generateSatellitesData(2);
+ setSatellites(mStatus);
+ Iterator<GpsSatellite> iterator = mStatus.getSatellites().iterator();
+ assertTrue("hasNext(1)", iterator.hasNext());
+ assertTrue("hasNext(1) does not overflow", iterator.hasNext());
+ GpsSatellite satellite1 = iterator.next();
+ assertNotNull("satellite", satellite1);
+ assertTrue("hasNext(2)", iterator.hasNext());
+ assertTrue("hasNext(2) does not overflow", iterator.hasNext());
+ GpsSatellite satellite2 = iterator.next();
+ assertNotNull("satellite", satellite2);
+ assertFalse("hasNext() no elements", iterator.hasNext());
+ }
+
+ public void testTtff() throws Exception {
+ int testTtff = generateInt();
+ set(mStatus, testTtff);
+ verifyTtff(mStatus, testTtff);
+ }
+
+ public void testCopyTtff() throws Exception {
+ int testTtff = generateInt();
+ verifyTtff(mStatus, 0);
+
+ GpsStatus otherStatus = createGpsStatus();
+ set(otherStatus, testTtff);
+ verifyTtff(otherStatus, testTtff);
+
+ set(mStatus, otherStatus);
+ verifyTtff(mStatus, testTtff);
+ }
+
+ public void testSetSatellites() throws Exception {
+ setSatellites(mStatus);
+ verifySatellites(mStatus);
+ }
+
+ public void testCopySatellites() throws Exception {
+ verifyIsEmpty(mStatus);
+
+ GpsStatus otherStatus = createGpsStatus();
+ setSatellites(otherStatus);
+ verifySatellites(otherStatus);
+
+ set(mStatus, otherStatus);
+ verifySatellites(mStatus);
+ }
+
+ public void testOverrideSatellites() throws Exception {
+ setSatellites(mStatus);
+ verifySatellites(mStatus);
+
+ GpsStatus otherStatus = createGpsStatus();
+ generateSatellitesData(mCount, true /* reusePrns */);
+ setSatellites(otherStatus);
+ verifySatellites(otherStatus);
+
+ set(mStatus, otherStatus);
+ verifySatellites(mStatus);
+ }
+
+ public void testAddSatellites() throws Exception {
+ int count = 10;
+ generateSatellitesData(count);
+ setSatellites(mStatus);
+ verifySatellites(mStatus);
+
+ GpsStatus otherStatus = createGpsStatus();
+ generateSatellitesData(count);
+ setSatellites(otherStatus);
+ verifySatellites(otherStatus);
+
+ set(mStatus, otherStatus);
+ verifySatellites(mStatus);
+ }
+
+ public void testAddMoreSatellites() throws Exception {
+ int count = 25;
+ generateSatellitesData(count);
+ setSatellites(mStatus);
+ verifySatellites(mStatus);
+
+ GpsStatus otherStatus = createGpsStatus();
+ generateSatellitesData(count * 2);
+ setSatellites(otherStatus);
+ verifySatellites(otherStatus);
+
+ set(mStatus, otherStatus);
+ verifySatellites(mStatus);
+ }
+
+ public void testAddLessSatellites() throws Exception {
+ int count = 25;
+ generateSatellitesData(count * 2);
+ setSatellites(mStatus);
+ verifySatellites(mStatus);
+
+ GpsStatus otherStatus = createGpsStatus();
+ generateSatellitesData(count);
+ setSatellites(otherStatus);
+ verifySatellites(otherStatus);
+
+ set(mStatus, otherStatus);
+ verifySatellites(mStatus);
+ }
+
+ private static void verifyIsEmpty(GpsStatus status) {
+ verifySatelliteCount(status, 0);
+ verifyTtff(status, 0);
+ }
+
+ private static void verifySatelliteCount(GpsStatus status, int expectedCount) {
+ int satellites = 0;
+ for (GpsSatellite s : status.getSatellites()) {
+ ++satellites;
+ }
+ assertEquals("GpsStatus::SatelliteCount", expectedCount, satellites);
+ }
+
+ private void verifySatellites(GpsStatus status) {
+ verifySatelliteCount(status, mCount);
+ verifySatellites(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask,
+ mAlmanacMask, mUsedInFixMask);
+ }
+
+ private static void verifySatellites(
+ GpsStatus status,
+ int count,
+ int[] prns,
+ float[] snrs,
+ float[] elevations,
+ float[] azimuth,
+ int ephemerisMask,
+ int almanacMask,
+ int usedInFixMask) {
+ for (int i = 0; i < count; ++i) {
+ int prn = prns[i];
+ GpsSatellite satellite = getSatellite(status, prn);
+ assertNotNull(getSatelliteAssertInfo(i, prn, "non-null"), satellite);
+ assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), snrs[i], satellite.getSnr());
+ assertEquals(
+ getSatelliteAssertInfo(i, prn, "Elevation"),
+ elevations[i],
+ satellite.getElevation());
+ assertEquals(
+ getSatelliteAssertInfo(i, prn, "Azimuth"),
+ azimuth[i],
+ satellite.getAzimuth());
+ int prnShift = 1 << (prn - 1);
+ assertEquals(
+ getSatelliteAssertInfo(i, prn, "ephemeris"),
+ (ephemerisMask & prnShift) != 0,
+ satellite.hasEphemeris());
+ assertEquals(
+ getSatelliteAssertInfo(i, prn, "almanac"),
+ (almanacMask & prnShift) != 0,
+ satellite.hasAlmanac());
+ assertEquals(
+ getSatelliteAssertInfo(i, prn, "usedInFix"),
+ (usedInFixMask & prnShift) != 0,
+ satellite.usedInFix());
+ }
+ }
+
+ private static void verifyTtff(GpsStatus status, int expectedTtff) {
+ assertEquals("GpsStatus::TTFF", expectedTtff, status.getTimeToFirstFix());
+ }
+
+ private static GpsStatus createGpsStatus() throws Exception {
+ Constructor<GpsStatus> ctor = GpsStatus.class.getDeclaredConstructor();
+ ctor.setAccessible(true);
+ return ctor.newInstance();
+ }
+
+ private static void set(GpsStatus status, int ttff) throws Exception {
+ Class<?> statusClass = status.getClass();
+ Method setTtff = statusClass.getDeclaredMethod("setTimeToFirstFix", Integer.TYPE);
+ setTtff.setAccessible(true);
+ setTtff.invoke(status, ttff);
+ }
+
+ private static void set(GpsStatus status, GpsStatus statusToSet) throws Exception {
+ Class<?> statusClass = status.getClass();
+ Method setStatus = statusClass.getDeclaredMethod("setStatus", statusClass);
+ setStatus.setAccessible(true);
+ setStatus.invoke(status, statusToSet);
+ }
+
+ private void setSatellites(GpsStatus status) throws Exception {
+ set(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
+ mUsedInFixMask);
+ }
+
+ private static void set(
+ GpsStatus status,
+ int count,
+ int[] prns,
+ float[] snrs,
+ float[] elevations,
+ float[] azimuth,
+ int ephemerisMask,
+ int almanacMask,
+ int usedInFixMask) throws Exception {
+ Class<?> statusClass = status.getClass();
+ Class<?> intClass = Integer.TYPE;
+ Class<?> floatArrayClass = Class.forName("[F");
+ Method setStatus = statusClass.getDeclaredMethod(
+ "setStatus",
+ intClass,
+ Class.forName("[I"),
+ floatArrayClass,
+ floatArrayClass,
+ floatArrayClass,
+ intClass,
+ intClass,
+ intClass);
+ setStatus.setAccessible(true);
+ setStatus.invoke(
+ status,
+ count,
+ prns,
+ snrs,
+ elevations,
+ azimuth,
+ ephemerisMask,
+ almanacMask,
+ usedInFixMask);
+ }
+
+ private int generateInt() {
+ return mRandom.nextInt(MAX_VALUE) + 1;
+ }
+
+ private int[] generateIntArray(int count) {
+ Set<Integer> generatedPrns = new HashSet<>();
+ int[] array = new int[count];
+ for(int i = 0; i < count; ++i) {
+ int generated;
+ do {
+ generated = generateInt();
+ } while (generatedPrns.contains(generated));
+ array[i] = generated;
+ generatedPrns.add(generated);
+ }
+ return array;
+ }
+
+ private float[] generateFloatArray(int count) {
+ float[] array = new float[count];
+ for(int i = 0; i < count; ++i) {
+ array[i] = generateInt();
+ }
+ return array;
+ }
+
+ private int generateMask(int[] prns) {
+ int mask = 0;
+ int prnsLength = prns.length;
+ for (int i = 0; i < prnsLength; ++i) {
+ if (mRandom.nextBoolean()) {
+ mask |= 1 << (prns[i] - 1);
+ }
+ }
+ return mask;
+ }
+
+ private void generateSatellitesData(int count) {
+ generateSatellitesData(count, false /* reusePrns */);
+ }
+
+ private void generateSatellitesData(int count, boolean reusePrns) {
+ mCount = count;
+ if (!reusePrns) {
+ mPrns = generateIntArray(count);
+ }
+ mSnrs = generateFloatArray(count);
+ mElevations = generateFloatArray(count);
+ mAzimuth = generateFloatArray(count);
+ mEphemerisMask = generateMask(mPrns);
+ mAlmanacMask = generateMask(mPrns);
+ mUsedInFixMask = generateMask(mPrns);
+ }
+
+ private static GpsSatellite getSatellite(GpsStatus status, int prn) {
+ for (GpsSatellite satellite : status.getSatellites()) {
+ if (satellite.getPrn() == prn) {
+ return satellite;
+ }
+ }
+ return null;
+ }
+
+ private static String getSatelliteAssertInfo(int index, int prn, String param) {
+ return String.format("Satellite::%s [i=%d, prn=%d]", param, index, prn);
+ }
+}