1 package android.location.cts.gnss;
2 
3 import android.location.cts.common.GnssTestCase;
4 import android.location.cts.common.SoftAssert;
5 import android.location.cts.common.TestLocationListener;
6 import android.location.cts.common.TestLocationManager;
7 import android.location.cts.common.TestUtils;
8 import android.net.ConnectivityManager;
9 import android.net.NetworkInfo;
10 import android.os.SystemClock;
11 import android.platform.test.annotations.AppModeFull;
12 import android.telephony.TelephonyManager;
13 import android.util.Log;
14 
15 import com.android.compatibility.common.util.CddTest;
16 
17 import java.util.concurrent.TimeUnit;
18 
19 /**
20  * Tests for the ttff (time to the first fix) validating whether TTFF is
21  * below the expected thresholds in differnt scenario
22  */
23 public class GnssTtffTests extends GnssTestCase {
24 
25   private static final String TAG = "GnssTtffTests";
26   private static final int LOCATION_TO_COLLECT_COUNT = 1;
27   private static final int STATUS_TO_COLLECT_COUNT = 3;
28   private static final int AIDING_DATA_RESET_DELAY_SECS = 10;
29   // Threshold values
30   private static final int TTFF_HOT_TH_SECS = 5;
31   private static final int TTFF_WITH_WIFI_CELLUAR_COLD_TH_SECS = 10;
32   // The worst case we saw in the Nexus 6p device is 15sec,
33   // adding 20% margin to the threshold
34   private static final int TTFF_WITH_WIFI_ONLY_COLD_TH_SECS = 18;
35 
36   @Override
setUp()37   protected void setUp() throws Exception {
38     super.setUp();
39     mTestLocationManager = new TestLocationManager(getContext());
40   }
41 
42   /**
43    * Test the TTFF in the case where there is a network connection for both cold and hot start TTFF
44    * cases.
45    * We first test the "COLD" start where different TTFF thresholds are chosen based on network
46    * connection (cellular vs Wifi). Then we test the "HOT" start where the type of network
47    * connection should not matter hence one threshold is used.
48    * @throws Exception
49    */
50   @CddTest(requirement="7.3.3")
51   @AppModeFull(reason = "permission ACCESS_LOCATION_EXTRA_COMMANDS not available to instant apps")
testTtffWithNetwork()52   public void testTtffWithNetwork() throws Exception {
53     if (!TestUtils.deviceHasGpsFeature(getContext())) {
54       return;
55     }
56 
57     ensureNetworkStatus();
58     if (hasCellularData()) {
59       checkTtffColdWithWifiOn(TTFF_WITH_WIFI_CELLUAR_COLD_TH_SECS);
60     }
61     else {
62       checkTtffColdWithWifiOn(TTFF_WITH_WIFI_ONLY_COLD_TH_SECS);
63     }
64     checkTtffHotWithWifiOn(TTFF_HOT_TH_SECS);
65   }
66 
67   /**
68    * Test Scenario 1
69    * Check whether TTFF is below the threshold on the cold start with Wifi ON
70    * 1) Delete the aiding data.
71    * 2) Get GPS, check the TTFF value
72    * @param threshold, the threshold for the TTFF value
73    */
checkTtffColdWithWifiOn(long threshold)74   private void checkTtffColdWithWifiOn(long threshold) throws Exception {
75     SoftAssert softAssert = new SoftAssert(TAG);
76     mTestLocationManager.sendExtraCommand("delete_aiding_data");
77     Thread.sleep(TimeUnit.SECONDS.toMillis(AIDING_DATA_RESET_DELAY_SECS));
78     checkTtffByThreshold("checkTtffColdWithWifiOn",
79         TimeUnit.SECONDS.toMillis(threshold), softAssert);
80     softAssert.assertAll();
81   }
82 
83   /**
84    * Test Scenario 2
85    * Check whether TTFF is below the threhold on the hot start with wifi ON
86    * TODO(tccyp): to test the hot case with network connection off
87    * @param threshold, the threshold for the TTFF value
88    */
checkTtffHotWithWifiOn(long threshold)89   private void checkTtffHotWithWifiOn(long threshold) throws Exception {
90     SoftAssert softAssert = new SoftAssert(TAG);
91     checkTtffByThreshold("checkTtffHotWithWifiOn",
92         TimeUnit.SECONDS.toMillis(threshold), softAssert);
93     softAssert.assertAll();
94   }
95 
96   /**
97    * Make sure the device has either wifi data or cellular connection
98    */
ensureNetworkStatus()99   private void ensureNetworkStatus(){
100     assertTrue("Device has to connect to Wifi or Cellular to complete this test.",
101         TestUtils.isConnectedToWifiOrCellular(getContext()));
102 
103   }
104 
hasCellularData()105   private boolean hasCellularData() {
106     ConnectivityManager connManager = TestUtils.getConnectivityManager(getContext());
107     NetworkInfo cellularNetworkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
108     // check whether the cellular data is ON if the device has cellular capability
109     if (cellularNetworkInfo == null) {
110       Log.i(TAG, "This is a wifi only device.");
111       return false;
112     }
113     TelephonyManager telephonyManager = (TelephonyManager) getContext().getApplicationContext()
114         .getSystemService(getContext().TELEPHONY_SERVICE);
115     if (!telephonyManager.isDataEnabled()) {
116       Log.i(TAG, "Device doesn't have cellular data.");
117       return false;
118     }
119     return true;
120   }
121 
122   /*
123    * Check whether TTFF is below the threshold
124    * @param testName
125    * @param threshold, the threshold for the TTFF value
126    */
checkTtffByThreshold(String testName, long threshold, SoftAssert softAssert)127   private void checkTtffByThreshold(String testName,
128       long threshold, SoftAssert softAssert) throws Exception {
129     TestLocationListener networkLocationListener
130         = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
131     // fetch the networklocation first to make sure the ttff is not flaky
132     mTestLocationManager.requestNetworkLocationUpdates(networkLocationListener);
133     networkLocationListener.await();
134 
135     TestGnssStatusCallback testGnssStatusCallback =
136         new TestGnssStatusCallback(TAG, STATUS_TO_COLLECT_COUNT);
137     mTestLocationManager.registerGnssStatusCallback(testGnssStatusCallback);
138 
139     TestLocationListener locationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
140     mTestLocationManager.requestLocationUpdates(locationListener);
141 
142 
143     long startTimeMillis = SystemClock.elapsedRealtime();
144     boolean success = testGnssStatusCallback.awaitTtff();
145     long ttffTimeMillis = SystemClock.elapsedRealtime() - startTimeMillis;
146 
147     softAssert.assertTrue(
148             "Test case:" + testName
149             + ". Threshold exceeded without getting a location."
150             + " Possibly, the test has been run deep indoors."
151             + " Consider retrying test outdoors.",
152         success);
153     mTestLocationManager.removeLocationUpdates(locationListener);
154     mTestLocationManager.unregisterGnssStatusCallback(testGnssStatusCallback);
155     softAssert.assertTrue("Test case: " + testName +", TTFF should be less than " + threshold
156         + " . In current test, TTFF value is: " + ttffTimeMillis, ttffTimeMillis < threshold);
157   }
158 }
159