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 package com.android.cts.verifier.sensors.sixdof.Fragments; 17 18 import com.android.cts.verifier.R; 19 import com.android.cts.verifier.sensors.sixdof.BuildConfig; 20 import com.android.cts.verifier.sensors.sixdof.Activities.TestActivity; 21 import com.android.cts.verifier.sensors.sixdof.Dialogs.RobustnessResultDialog; 22 import com.android.cts.verifier.sensors.sixdof.Interfaces.RobustnessListener; 23 import com.android.cts.verifier.sensors.sixdof.Renderer.RobustnessRenderer; 24 import com.android.cts.verifier.sensors.sixdof.Renderer.RenderUtils.Colour; 25 import com.android.cts.verifier.sensors.sixdof.Utils.Manager; 26 import com.android.cts.verifier.sensors.sixdof.Utils.Exceptions.WaypointAreaCoveredException; 27 import com.android.cts.verifier.sensors.sixdof.Utils.Exceptions.WaypointDistanceException; 28 import com.android.cts.verifier.sensors.sixdof.Utils.Exceptions.WaypointRingNotEnteredException; 29 import com.android.cts.verifier.sensors.sixdof.Utils.Exceptions.WaypointStartPointException; 30 import com.android.cts.verifier.sensors.sixdof.Utils.Path.PathUtilityClasses.RotationData; 31 import com.android.cts.verifier.sensors.sixdof.Utils.ResultObjects.ResultObject; 32 33 import android.app.Activity; 34 import android.opengl.GLSurfaceView; 35 import android.os.Bundle; 36 import android.app.AlertDialog; 37 import android.util.Log; 38 import android.view.LayoutInflater; 39 import android.view.View; 40 import android.view.ViewGroup; 41 import android.widget.ImageButton; 42 import android.widget.LinearLayout; 43 import android.widget.TextView; 44 import android.widget.Toast; 45 46 /** 47 * UI fragment for the second test. 48 */ 49 public class RobustnessFragment extends BaseUiFragment implements RobustnessListener { 50 private static final String TAG = "RobustnessFragment"; 51 private static final Object TIMER_LOCK = new Object(); 52 53 private TextView mTvTime; 54 private TextView mTvPassColour; 55 private TextView mTvObjective; 56 57 private boolean mIsPassing = false; 58 private boolean mResultGiven = false; 59 60 /** 61 * Standard practice to have a static newInstance constructor. Used to pass in arguments to the 62 * fragment. We don't have any at the moment, but this is good structure for the future. 63 * 64 * @return a new Robustness test fragment. 65 */ newInstance()66 public static RobustnessFragment newInstance() { 67 RobustnessFragment fragment = new RobustnessFragment(); 68 return fragment; 69 } 70 71 /** 72 * Called when the parent activity has been created. Adds the GLSurfaceView to the fragment 73 * layout. 74 */ 75 @Override onActivityCreated(Bundle savedInstanceState)76 public void onActivityCreated(Bundle savedInstanceState) { 77 super.onActivityCreated(savedInstanceState); 78 79 GLSurfaceView surfaceView = new GLSurfaceView(getActivity()); 80 surfaceView.setEGLContextClientVersion(2); 81 mRenderer = new RobustnessRenderer(getActivity()); 82 surfaceView.setRenderer(mRenderer); 83 mLLCameraLayout = (LinearLayout) getView().findViewById(R.id.llCamera); 84 mLLCameraLayout.addView(surfaceView); 85 Log.d(TAG, "Camera Preview add to layout"); 86 } 87 88 /** 89 * Initialises all of the UI elements. 90 */ 91 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)92 public View onCreateView(LayoutInflater inflater, ViewGroup container, 93 Bundle savedInstanceState) { 94 View view = inflater.inflate(R.layout.fragment_robustness, container, false); 95 getActivity().setTitle(getResources().getStringArray(R.array.phase)[TestActivity.CTSTest.ROBUSTNESS.ordinal()]); 96 97 // Set up pass/info/fail buttons 98 setupButtons(view, TestActivity.CTSTest.ROBUSTNESS); 99 100 mPlaceWaypointButton = (ImageButton) view.findViewById(R.id.fabPlaceWaypoint); 101 mPlaceWaypointButton.setOnClickListener(new View.OnClickListener() { 102 @Override 103 public void onClick(View v) { 104 try { 105 mActivity.attemptWaypointPlacement(); 106 } catch (WaypointDistanceException e) { 107 Toast.makeText(getActivity(), 108 getString(R.string.error_distance), Toast.LENGTH_SHORT).show(); 109 } catch (WaypointAreaCoveredException e) { 110 Toast.makeText(getActivity(), 111 getString(R.string.error_area), Toast.LENGTH_SHORT).show(); 112 } catch (WaypointStartPointException e) { 113 Toast.makeText(getActivity(), 114 getString(R.string.error_start_point), Toast.LENGTH_SHORT).show(); 115 } catch (WaypointRingNotEnteredException e) { 116 throw new AssertionError( 117 "WaypointRingNotEnteredException when not in 3rd test", e); 118 } 119 } 120 }); 121 122 mTvTime = (TextView) view.findViewById(R.id.tvTimer); 123 mTvPassColour = (TextView) view.findViewById(R.id.tvPassColour); 124 mTvObjective = (TextView) view.findViewById(R.id.tvObjective); 125 126 return view; 127 } 128 129 /** 130 * Called after onCreateView. Starts listening for 6DoF events. 131 */ 132 @Override onViewCreated(View view, Bundle savedInstanceState)133 public void onViewCreated(View view, Bundle savedInstanceState) { 134 super.onViewCreated(view, savedInstanceState); 135 mActivity.listenFor6DofData(this); 136 } 137 138 @Override setupUILoop()139 protected void setupUILoop() { 140 Runnable runnable = new Runnable() { 141 @Override 142 public void run() { 143 if (mActivity == null || getActivity() == null) { 144 return; 145 } 146 147 String stringTimeRemaining; 148 String decimalTimeRemaining = (mActivity.getTimeRemaining() / 1000f) + ""; 149 synchronized (TIMER_LOCK) { 150 stringTimeRemaining = String.format(getString(R.string.time_remaining), decimalTimeRemaining); 151 } 152 153 synchronized (TIMER_LOCK) { 154 if (mIsPassing) { 155 mTvPassColour.setBackgroundColor(getResources().getColor(R.color.green)); 156 } else { 157 mTvPassColour.setBackgroundColor(getResources().getColor(R.color.red)); 158 } 159 } 160 161 int waypointCount = mActivity.getUserGeneratedWaypoints(Manager.Lap.LAP_3).size(); 162 mTvObjective.setText(getObjectiveText(Manager.Lap.LAP_3, waypointCount)); 163 164 if (waypointCount < Manager.MAX_MARKER_NUMBER && !mResultGiven) { 165 mPlaceWaypointButton.setVisibility(View.VISIBLE); 166 mTvTime.setText(stringTimeRemaining); 167 } else { 168 mTvTime.setText(""); 169 } 170 171 //Update the UI again in x milliseconds. 172 if (mHandler != null) { 173 mHandler.postDelayed(this, UI_UPDATE_DELAY); 174 } 175 } 176 }; 177 178 super.initUIHandler(runnable); 179 } 180 181 /** 182 * Shows initial instruction dialog. 183 */ 184 @Override showInitialDialog()185 protected void showInitialDialog() { 186 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 187 188 builder.setMessage(R.string.phase2_initial_message) 189 .setTitle(getResources().getStringArray(R.array.phase)[TestActivity.CTSTest.ROBUSTNESS.ordinal()]) 190 .setPositiveButton(R.string.got_it, null); 191 192 AlertDialog dialog = builder.create(); 193 dialog.show(); 194 } 195 196 @Override onResult(final ResultObject result)197 public void onResult(final ResultObject result) { 198 getActivity().runOnUiThread(new Runnable() { 199 @Override 200 public void run() { 201 mResultGiven = true; 202 RobustnessResultDialog dialog = RobustnessResultDialog.newInstance(result); 203 dialog.setTargetFragment(RobustnessFragment.this, DIALOG_FRAGMENT); 204 dialog.show(getActivity().getFragmentManager(), "ResultDialogFragment"); 205 mPlaceWaypointButton.setVisibility(View.INVISIBLE); 206 207 if (result.hasPassed() || BuildConfig.DEBUG) { 208 mBtnPass.setEnabled(true); 209 mBtnPass.setOnClickListener(new View.OnClickListener() { 210 @Override 211 public void onClick(View view) { 212 onReadyForPhase3(); 213 } 214 }); 215 } 216 } 217 }); 218 } 219 onReadyForPhase3()220 private void onReadyForPhase3() { 221 mActivity.switchToStartFragment(TestActivity.CTSTest.COMPLEX_MOVEMENT); 222 } 223 224 @Override onNewRotationData(RotationData data)225 public void onNewRotationData(RotationData data) { 226 synchronized (TIMER_LOCK) { 227 mIsPassing = data.getRotationTestState(); 228 } 229 230 if (mRenderer != null) { 231 if (data.getRotationTestState()) { 232 ((RobustnessRenderer) mRenderer).setLineColor(Colour.GREEN); 233 } else { 234 ((RobustnessRenderer) mRenderer).setLineColor(Colour.RED); 235 } 236 237 if (mActivity.getUserGeneratedWaypoints(Manager.Lap.LAP_3).size() > 0) { 238 ((RobustnessRenderer) mRenderer).updateCurrentAngle(data.getCurrentAngle()); 239 ((RobustnessRenderer) mRenderer).updateTargetAngle(data.getTargetAngle()); 240 } 241 } 242 } 243 } 244