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.StartActivity;
21 import com.android.cts.verifier.sensors.sixdof.Activities.TestActivity;
22 import com.android.cts.verifier.sensors.sixdof.Dialogs.ComplexMovementResultDialog;
23 import com.android.cts.verifier.sensors.sixdof.Interfaces.ComplexMovementListener;
24 import com.android.cts.verifier.sensors.sixdof.Renderer.ComplexMovementRenderer;
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.ComplexMovementPath;
31 import com.android.cts.verifier.sensors.sixdof.Utils.Path.PathUtilityClasses.Ring;
32 import com.android.cts.verifier.sensors.sixdof.Utils.ResultObjects.ResultObject;
33 
34 import android.app.Activity;
35 import android.content.Intent;
36 import android.opengl.GLSurfaceView;
37 import android.os.Bundle;
38 import android.app.AlertDialog;
39 import android.util.Log;
40 import android.view.LayoutInflater;
41 import android.view.View;
42 import android.view.ViewGroup;
43 import android.widget.ImageButton;
44 import android.widget.LinearLayout;
45 import android.widget.TextView;
46 import android.widget.Toast;
47 
48 import java.io.IOException;
49 
50 /**
51  * UI fragment for the third test.
52  */
53 public class ComplexMovementFragment extends BaseUiFragment implements ComplexMovementListener {
54     private static final String TAG = "ComplexMovementFragment";
55 
56     private TextView mTvObjective;
57     private TextView mTvRings;
58 
59     /**
60      * Standard practice to have a static newInstance constructor. Used to pass in arguments to the
61      * fragment. We don't have any at the moment, but this is good structure for the future.
62      *
63      * @return a new Robustness test fragment.
64      */
newInstance()65     public static ComplexMovementFragment newInstance() {
66         return new ComplexMovementFragment();
67     }
68 
69     /**
70      * Called when the parent activity has been created. Adds the GLSurfaceView to the fragment
71      * layout.
72      */
73     @Override
onActivityCreated(Bundle savedInstanceState)74     public void onActivityCreated(Bundle savedInstanceState) {
75         super.onActivityCreated(savedInstanceState);
76 
77         GLSurfaceView surfaceView = new GLSurfaceView(getActivity());
78         surfaceView.setEGLContextClientVersion(2);
79         mRenderer = new ComplexMovementRenderer(getActivity(), mActivity.getRings());
80         surfaceView.setRenderer(mRenderer);
81         mLLCameraLayout = (LinearLayout) getView().findViewById(R.id.llCamera);
82         mLLCameraLayout.addView(surfaceView);
83         Log.d(TAG, "Camera Preview add to layout");
84     }
85 
86     /**
87      * Initialises all of the UI elements
88      */
89     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)90     public View onCreateView(LayoutInflater inflater, ViewGroup container,
91                              Bundle savedInstanceState) {
92         View view = inflater.inflate(R.layout.fragment_complex_movement, container, false);
93         getActivity().setTitle(getResources().getStringArray(R.array.phase)[TestActivity.CTSTest.COMPLEX_MOVEMENT.ordinal()]);
94 
95         // Set up pass/info/fail buttons.
96         setupButtons(view, TestActivity.CTSTest.COMPLEX_MOVEMENT);
97 
98         mPlaceWaypointButton = (ImageButton) view.findViewById(R.id.fabPlaceWaypoint);
99         mPlaceWaypointButton.setOnClickListener(new View.OnClickListener() {
100             @Override
101             public void onClick(View v) {
102                 try {
103                     mActivity.attemptWaypointPlacement();
104                 } catch (WaypointAreaCoveredException e) {
105                     Toast.makeText(getActivity(),
106                             getString(R.string.error_area), Toast.LENGTH_SHORT).show();
107                 } catch (WaypointDistanceException e) {
108                     Toast.makeText(getActivity(),
109                             getString(R.string.error_distance), Toast.LENGTH_SHORT).show();
110                 } catch (WaypointStartPointException e) {
111                     Toast.makeText(getActivity(),
112                             getString(R.string.error_start_point), Toast.LENGTH_SHORT).show();
113                 } catch (WaypointRingNotEnteredException e) {
114                     Toast.makeText(getActivity(),
115                             getString(R.string.error_rings_not_entered), Toast.LENGTH_SHORT).show();
116                 }
117             }
118         });
119 
120         mTvObjective = (TextView) view.findViewById(R.id.tvObjective);
121         mTvRings = (TextView) view.findViewById(R.id.tvRings);
122 
123         return view;
124     }
125 
126     /**
127      * Called after onCreateView. Starts listening for 6DoF events.
128      */
129     @Override
onViewCreated(View view, Bundle savedInstanceState)130     public void onViewCreated(View view, Bundle savedInstanceState) {
131         super.onViewCreated(view, savedInstanceState);
132         mActivity.listenFor6DofData(this);
133     }
134 
135     @Override
setupUILoop()136     protected void setupUILoop() {
137         Runnable runnable = new Runnable() {
138             @Override
139             public void run() {
140                 if (mActivity == null || getActivity() == null) {
141                     return;
142                 }
143 
144                 int waypointCount = mActivity.getUserGeneratedWaypoints(Manager.Lap.LAP_4).size();
145                 mTvObjective.setText(getObjectiveText(Manager.Lap.LAP_4, waypointCount));
146 
147                 int ringCount = 0;
148                 for (Ring ring : mActivity.getRings()) {
149                     if (ring.getPathNumber() == waypointCount && ring.isEntered()) {
150                         ringCount++;
151                     }
152                 }
153 
154                 mTvRings.setText(String.format(getString(R.string.rings_entered),
155                         ringCount, ComplexMovementPath.RINGS_PER_PATH));
156 
157                 if (waypointCount < Manager.MAX_MARKER_NUMBER) {
158                     mPlaceWaypointButton.setVisibility(View.VISIBLE);
159                 }
160 
161                 // Update the UI again in x milliseconds.
162                 if (mHandler != null) {
163                     mHandler.postDelayed(this, UI_UPDATE_DELAY);
164                 }
165             }
166         };
167 
168         super.initUIHandler(runnable);
169     }
170 
171     /**
172      * Shows initial instruction dialog
173      */
174     @Override
showInitialDialog()175     protected void showInitialDialog() {
176         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
177 
178         builder.setMessage(R.string.phase3_initial_message)
179                 .setTitle(getResources().getStringArray(R.array.phase)[TestActivity.CTSTest.COMPLEX_MOVEMENT.ordinal()])
180                 .setPositiveButton(R.string.got_it, null);
181 
182         AlertDialog dialog = builder.create();
183         dialog.show();
184     }
185 
186     @Override
onWaypointPlaced()187     public void onWaypointPlaced() {
188         super.onWaypointPlaced();
189         ((ComplexMovementRenderer) mRenderer).onWaypointPlaced(mActivity.getUserGeneratedWaypoints(Manager.Lap.LAP_4).size());
190     }
191 
192     @Override
onRingEntered(Ring ring)193     public void onRingEntered(Ring ring) {
194         ((ComplexMovementRenderer) mRenderer).onRingEntered(ring);
195     }
196 
197     @Override
onResult(ResultObject result)198     public void onResult(ResultObject result) {
199         ComplexMovementResultDialog dialog = ComplexMovementResultDialog.newInstance(result);
200         dialog.setTargetFragment(ComplexMovementFragment.this, DIALOG_FRAGMENT);
201         dialog.show(getActivity().getFragmentManager(), "ResultDialogFragment");
202         mPlaceWaypointButton.setVisibility(View.INVISIBLE);
203 
204         if (result.hasPassed() || BuildConfig.DEBUG) {
205             mBtnPass.setEnabled(true);
206             mBtnPass.setOnClickListener(new View.OnClickListener() {
207                 @Override
208                 public void onClick(View view) {
209                     finishTest();
210                 }
211             });
212         }
213     }
214 
finishTest()215     private void finishTest() {
216         Intent resultIntent = getActivity().getIntent();
217         String report = "Couldn't create test report.";
218         try {
219             report = mActivity.getTestReport().getContents();
220         } catch (IOException e) {
221             Log.e(TAG, report);
222         }
223         resultIntent.putExtra(TestActivity.EXTRA_REPORT, report);
224         resultIntent.putExtra(TestActivity.EXTRA_RESULT_ID, StartActivity.ResultCode.PASSED);
225         getActivity().setResult(Activity.RESULT_OK, resultIntent);
226         getActivity().finish();
227     }
228 }
229