1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts.verifier.sensors.sixdof.Utils.TestPhase;
18 
19 
20 import com.android.cts.verifier.sensors.sixdof.Dialogs.BaseResultsDialog;
21 import com.android.cts.verifier.sensors.sixdof.Utils.Manager;
22 import com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils;
23 import com.android.cts.verifier.sensors.sixdof.Utils.TestReport;
24 import com.android.cts.verifier.sensors.sixdof.Utils.Path.ReferencePath;
25 import com.android.cts.verifier.sensors.sixdof.Utils.Path.RobustnessPath;
26 import com.android.cts.verifier.sensors.sixdof.Utils.Path.PathUtilityClasses.RotationData;
27 
28 import android.util.Log;
29 
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 
33 /**
34  * Handles all the Robustness test related features.
35  */
36 public class RobustnessTest extends Test {
37     private static final float MAXIMUM_PERCENT_ROTATION_FAILURE = 50f;
38     private boolean mResultsGiven = false;
39     private ArrayList<Long> mTimeDifferences = new ArrayList<>();
40     private float mDistanceOfPathToFail;
41 
42     /**
43      * Created a new robustness path which is to be used in this test.
44      *
45      * @param referencePath Reference the the reference path.
46      * @param testReport    The test report object to record the tests.
47      * @param manager       The manager to call when the test is done.
48      */
RobustnessTest(ReferencePath referencePath, TestReport testReport, Manager manager, int openGlRotation)49     public RobustnessTest(ReferencePath referencePath, TestReport testReport, Manager manager,
50                           int openGlRotation) {
51         super(referencePath, testReport, manager, "Robustness Test");
52         mTestPath = new RobustnessPath(openGlRotation);
53         float mPathTotalDistance = 0;
54         for (float distance : mReferencePathDistances) {
55             mPathTotalDistance += distance;
56         }
57         mDistanceOfPathToFail = (MAXIMUM_PERCENT_ROTATION_FAILURE / 100f) * mPathTotalDistance;
58     }
59 
60     /**
61      * Implementation of the abstract method which check whether the test is complete.
62      */
63     @Override
runAdditionalMethods()64     protected void runAdditionalMethods() {
65         if (mTestPath.getPathMarkersSize() == MAX_MARKER_NUMBER && !mResultsGiven) {
66             mResultsGiven = true;
67             executeRobustnessTests();
68         }
69     }
70 
71     /**
72      * Starts the robustness tests.
73      */
executeRobustnessTests()74     private void executeRobustnessTests() {
75         HashMap<BaseResultsDialog.ResultType, Boolean> robustnessTestResults;
76         robustnessTestResults = executeTests(true, true);
77         robustnessTestResults.put(BaseResultsDialog.ResultType.TIME, timerTest());
78         robustnessTestResults.put(BaseResultsDialog.ResultType.ROTATION, rotationTest());
79         mManager.onRobustnessTestCompleted(robustnessTestResults);
80     }
81 
82     /**
83      * Test to check whether the waypoint was placed in the appropriate time.
84      *
85      * @return true if all waypoint times were met, fail if a waypoint was placed after the time
86      * expired
87      */
timerTest()88     private boolean timerTest() {
89         calculateTimeBetweenMarkers();
90         boolean state = true;
91         for (int i = 0; i < mTimeDifferences.size(); i++) {
92             if (mTimeDifferences.get(i) > RobustnessPath.TIME_TO_ADD_MARKER) {
93                 recordTimerTestResults(i);
94                 state = false;
95             }
96         }
97         return state;
98     }
99 
100     /**
101      * Calculates the time it took to place a waypoint.
102      */
calculateTimeBetweenMarkers()103     private void calculateTimeBetweenMarkers() {
104         long timeDifference;
105         ArrayList<Long> markerTimeStamps = ((RobustnessPath) mTestPath).getMarkerTimeStamp();
106         for (int i = 1; i < ((RobustnessPath) mTestPath).getMarkerTimeStampSize(); i++) {
107             timeDifference = markerTimeStamps.get(i) - markerTimeStamps.get(i - 1);
108             mTimeDifferences.add(timeDifference);
109         }
110     }
111 
112     /**
113      * Formats the failed times into a string to add it to the test report.
114      *
115      * @param markerLocation The marker location which failed the test. Used to get the data needed
116      *                       for the test report
117      */
recordTimerTestResults(int markerLocation)118     private void recordTimerTestResults(int markerLocation) {
119         long failedTime = mTimeDifferences.get(markerLocation);
120         String markerToPlace = MathsUtils.coordinatesToString(
121                 mTestPath.getPathMarkers().get(markerLocation).getCoordinates());
122         String testDetails =
123                 "Timer test: Marker placement was too slow that timer expired. Target time: "
124                         + RobustnessPath.TIME_TO_ADD_MARKER / 1000 + " Completed time: " + Math.abs(failedTime) / 1000 +
125                         " Marker: " + markerLocation + " Coordinates:" + markerToPlace + "\n";
126         Log.e("Timer Result", testDetails);
127         mTestReport.setFailDetails(testDetails);
128     }
129 
130     /**
131      * Test to check whether the rotation test has passed based on the percent of failed rotations.
132      *
133      * @return true if the test passes, false if the test fails
134      */
rotationTest()135     private boolean rotationTest() {
136         float failedRotations = ((RobustnessPath) mTestPath).getFailedRotationsSize();
137         float totalRotations = ((RobustnessPath) mTestPath).getRobustnessPathRotationsSize();
138         float percentage = (failedRotations / totalRotations) * 100;
139         if (totalRotations == 0) {
140             Log.e("rotationResult", "Total was 0");
141             return false;
142         }
143         if (percentage > MAXIMUM_PERCENT_ROTATION_FAILURE) {
144             Log.d("rotationResult", "failed");
145             recordRotationTestResults(percentage, failedRotations, totalRotations);
146             return false;
147         } else {
148             Log.d("getFailedRotationSize", "" + failedRotations);
149             Log.d("total", "" + totalRotations);
150             Log.d("rotationResult", "passed ");
151             Log.d("rotationResult", "" + percentage);
152             return true;
153         }
154     }
155 
156     /**
157      * Formats the failed rotations into a string to add it to the test report.
158      *
159      * @param percentFailed   Percentage of failed rotations
160      * @param failedRotations number of failed rotations
161      * @param totalRotations  number of rotations made
162      */
recordRotationTestResults(float percentFailed, float failedRotations, float totalRotations)163     private void recordRotationTestResults(float percentFailed, float failedRotations, float totalRotations) {
164         String testDetails =
165                 "Rotation test: Rotation fails were too great. Target rotation percent: "
166                         + MAXIMUM_PERCENT_ROTATION_FAILURE + " GivenRotation percent: " + percentFailed +
167                         " Failed rotation: " + failedRotations + " Total rotations:" + totalRotations + "\n";
168         Log.e("Timer Result", testDetails);
169         mTestReport.setFailDetails(testDetails);
170     }
171 
172     /**
173      * gets the result of comparing the current rotation
174      *
175      * @param rotationQuaternion The quaternions of the current rotation
176      * @param location           The location of the point with the rotation
177      * @return The rotation about the current rotation
178      */
getRotationData(float[] rotationQuaternion, float[] location)179     public RotationData getRotationData(float[] rotationQuaternion, float[] location) {
180         RotationData rotation = ((RobustnessPath) mTestPath).handleRotation(
181                 rotationQuaternion, location, mReferencePath.getPathMarkers(), mDistanceOfPathToFail);
182         if (rotation == null) {
183             if (!mResultsGiven) {
184                 mResultsGiven = true;
185                 HashMap<BaseResultsDialog.ResultType, Boolean> testFailed = new HashMap<>();
186                 testFailed.put(BaseResultsDialog.ResultType.WAYPOINT, false);
187                 testFailed.put(BaseResultsDialog.ResultType.PATH, false);
188                 testFailed.put(BaseResultsDialog.ResultType.TIME, false);
189                 testFailed.put(BaseResultsDialog.ResultType.ROTATION, false);
190                 String testDetails = "Test terminated as it its impossible to pass the remaining rotations";
191                 Log.e("Rotation test:", mDistanceOfPathToFail + "");
192                 Log.e("Rotation test:", testDetails);
193                 mTestReport.setFailDetails(testDetails);
194                 mManager.onRobustnessTestCompleted(testFailed);
195             }
196             return null;
197         } else {
198             return rotation;
199         }
200 
201     }
202 
203     /**
204      * Returns the time remaining for the user to place the marker
205      */
getTimeRemaining()206     public long getTimeRemaining() {
207         return ((RobustnessPath) mTestPath).calculateTimeRemaining();
208     }
209 }
210