• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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;
18 
19 import android.app.AlertDialog;
20 import android.content.ActivityNotFoundException;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.Intent;
24 import android.database.DataSetObserver;
25 import android.os.Bundle;
26 import android.util.Log;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 import android.view.View.OnClickListener;
30 import android.widget.Button;
31 import android.widget.ImageView;
32 import android.widget.ListView;
33 import android.widget.TextView;
34 import android.widget.Toast;
35 
36 import com.android.cts.verifier.R;
37 
38 /**
39  * Test list activity that supports showing dialogs with pass/fail buttons instead of
40  * starting new activities.
41  * In addition to that dialogs have a 'go' button that can be configured to launch an intent.
42  * Instructions are shown on top of the screen and a test preparation button is provided.
43  */
44 public abstract class DialogTestListActivity extends PassFailButtons.TestListActivity {
45     private final String TAG = "DialogTestListActivity";
46     private final int mLayoutId;
47     private final int mTitleStringId;
48     private final int mInfoStringId;
49     private final int mInstructionsStringId;
50 
51     protected Button mPrepareTestButton;
52 
53     protected int mCurrentTestPosition;
54 
DialogTestListActivity(int layoutId, int titleStringId, int infoStringId, int instructionsStringId)55     protected DialogTestListActivity(int layoutId, int titleStringId, int infoStringId,
56             int instructionsStringId) {
57         mLayoutId = layoutId;
58         mTitleStringId = titleStringId;
59         mInfoStringId = infoStringId;
60         mInstructionsStringId = instructionsStringId;
61     }
62 
63     @Override
onCreate(Bundle savedInstanceState)64     protected void onCreate(Bundle savedInstanceState) {
65         super.onCreate(savedInstanceState);
66 
67         setContentView(mLayoutId);
68         setInfoResources(mTitleStringId, mInfoStringId, -1);
69         setPassFailButtonClickListeners();
70         getPassButton().setEnabled(false);
71         setResult(RESULT_CANCELED);
72 
73         ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
74 
75         setupTests(adapter);
76 
77         adapter.registerDataSetObserver(new DataSetObserver() {
78             @Override
79             public void onChanged() {
80                 updatePassButton();
81             }
82         });
83 
84         setTestListAdapter(adapter);
85 
86         mCurrentTestPosition = 0;
87 
88         TextView instructionTextView = (TextView)findViewById(R.id.test_instructions);
89         instructionTextView.setText(mInstructionsStringId);
90         mPrepareTestButton = (Button)findViewById(R.id.prepare_test_button);
91     }
92 
93     /**
94      * Subclasses must add their tests items to the provided adapter(usually instances of
95      * {@link DialogTestListItem} or {@link DialogTestListItemWithIcon} but any class deriving from
96      * {@link TestListAdapter.TestListItem} will do).
97      * @param adapter The adapter to add test items to.
98      */
setupTests(ArrayTestListAdapter adapter)99     protected abstract void setupTests(ArrayTestListAdapter adapter);
100 
101     // Enable Pass Button when all tests passed.
updatePassButton()102     private void updatePassButton() {
103         getPassButton().setEnabled(mAdapter.allTestsPassed());
104     }
105 
106     public class DefaultTestCallback implements DialogTestListItem.TestCallback {
107         final private DialogTestListItem mTest;
108 
DefaultTestCallback(DialogTestListItem test)109         public DefaultTestCallback(DialogTestListItem test) {
110             mTest = test;
111         }
112 
113         @Override
onPass()114         public void onPass() {
115             clearRemainingState(mTest);
116             setTestResult(mTest, TestResult.TEST_RESULT_PASSED);
117         }
118 
119         @Override
onFail()120         public void onFail() {
121             clearRemainingState(mTest);
122             setTestResult(mTest, TestResult.TEST_RESULT_FAILED);
123         }
124     }
125 
showManualTestDialog(final DialogTestListItem test)126     public void showManualTestDialog(final DialogTestListItem test) {
127         showManualTestDialog(test, new DefaultTestCallback(test));
128     }
129 
showManualTestDialog(final DialogTestListItem test, final DialogTestListItem.TestCallback callback)130     public void showManualTestDialog(final DialogTestListItem test,
131             final DialogTestListItem.TestCallback callback) {
132         AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this)
133                 .setIcon(android.R.drawable.ic_dialog_info)
134                 .setTitle(mTitleStringId)
135                 .setNeutralButton(R.string.go_button_text, null)
136                 .setPositiveButton(R.string.pass_button_text, new AlertDialog.OnClickListener() {
137                     @Override
138                     public void onClick(DialogInterface dialog, int which) {
139                         callback.onPass();
140                     }
141                 })
142                 .setNegativeButton(R.string.fail_button_text, new AlertDialog.OnClickListener() {
143                     @Override
144                     public void onClick(DialogInterface dialog, int which) {
145                         callback.onFail();
146                     }
147                 });
148         View customView = test.getCustomView();
149         if (customView != null) {
150             dialogBuilder.setView(customView);
151         } else {
152             dialogBuilder.setMessage(test.getManualTestInstruction());
153         }
154         final AlertDialog dialog = dialogBuilder.show();
155         // Note: Setting the OnClickListener on the Dialog rather than the Builder, prevents the
156         // dialog being dismissed on onClick.
157         dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() {
158             @Override
159             public void onClick(View v) {
160                 if (!startTestIntent(test)) {
161                     dialog.dismiss();
162                 }
163             }
164         });
165     }
166 
167     @Override
handleItemClick(ListView l, View v, int position, long id)168     protected void handleItemClick(ListView l, View v, int position, long id) {
169         TestListAdapter.TestListItem test = (TestListAdapter.TestListItem) getListAdapter()
170                 .getItem(position);
171         if (test instanceof DialogTestListItem) {
172             mCurrentTestPosition = position;
173             ((DialogTestListItem)test).performTest(this);
174         } else {
175             try {
176                 super.handleItemClick(l, v, position, id);
177             } catch (ActivityNotFoundException e) {
178                 Log.d(TAG, "handleItemClick() threw exception: ", e);
179                 setTestResult(test, TestResult.TEST_RESULT_FAILED);
180                 showToast(R.string.test_failed_cannot_start_intent);
181             }
182         }
183     }
184 
185 
186     /**
187      * Start a test's manual intent
188      * @param test The test the manual intent of which is to be started.
189      * @return true if activity could be started successfully, false otherwise.
190      */
startTestIntent(final DialogTestListItem test)191     boolean startTestIntent(final DialogTestListItem test) {
192         final Intent intent = test.intent;
193         try {
194             startActivity(intent);
195         } catch (ActivityNotFoundException e) {
196             Toast.makeText(this, "Cannot start " + intent, Toast.LENGTH_LONG).show();
197             setTestResult(test, TestResult.TEST_RESULT_FAILED);
198             return false;
199         }
200         return true;
201     }
202 
clearRemainingState(final DialogTestListItem test)203     protected void clearRemainingState(final DialogTestListItem test) {
204         // do nothing, override in subclass if needed
205     }
206 
setTestResult(TestListAdapter.TestListItem test, int result)207     protected void setTestResult(TestListAdapter.TestListItem test, int result) {
208         // Bundle result in an intent to feed into handleLaunchTestResult
209         Intent resultIntent = new Intent();
210         TestResult.addResultData(resultIntent, result, test.testName, /* testDetails */ null,
211                 /* reportLog */ null);
212         handleLaunchTestResult(RESULT_OK, resultIntent);
213         getListView().smoothScrollToPosition(mCurrentTestPosition + 1);
214     }
215 
showToast(int messageId)216     protected void showToast(int messageId) {
217         String message = getString(messageId);
218         Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
219     }
220 
221     protected static class DialogTestListItem extends TestListAdapter.TestListItem {
222 
223         public interface TestCallback {
onPass()224             void onPass();
onFail()225             void onFail();
226         }
227 
228         private String mManualInstruction;
229 
DialogTestListItem(Context context, int nameResId, String testId)230         public DialogTestListItem(Context context, int nameResId, String testId) {
231             super(context.getString(nameResId), testId, null, null, null, null);
232         }
233 
DialogTestListItem(Context context, int nameResId, String testId, int testInstructionResId, Intent testIntent)234         public DialogTestListItem(Context context, int nameResId, String testId,
235                 int testInstructionResId, Intent testIntent) {
236             super(context.getString(nameResId), testId, testIntent, null, null, null);
237             mManualInstruction = context.getString(testInstructionResId);
238         }
239 
performTest(DialogTestListActivity activity)240         public void performTest(DialogTestListActivity activity) {
241             activity.showManualTestDialog(this);
242         }
243 
getManualTestInstruction()244         public String getManualTestInstruction() {
245             return mManualInstruction;
246         }
247 
getManualTestIntent()248         public Intent getManualTestIntent() {
249             return intent;
250         }
251 
getCustomView()252         public View getCustomView() {
253             return null;
254         }
255 
256         @Override
isTest()257         boolean isTest() {
258             return true;
259         }
260     }
261 
262     protected static class DialogTestListItemWithIcon extends DialogTestListItem {
263 
264         private final int mImageResId;
265         private final Context mContext;
266 
DialogTestListItemWithIcon(Context context, int nameResId, String testId, int testInstructionResId, Intent testIntent, int imageResId)267         public DialogTestListItemWithIcon(Context context, int nameResId, String testId,
268                 int testInstructionResId, Intent testIntent, int imageResId) {
269             super(context, nameResId, testId, testInstructionResId, testIntent);
270             mContext = context;
271             mImageResId = imageResId;
272         }
273 
274         @Override
getCustomView()275         public View getCustomView() {
276             LayoutInflater layoutInflater = LayoutInflater.from(mContext);
277             View view = layoutInflater.inflate(R.layout.dialog_custom_view,
278                     null /* root */);
279             ((ImageView) view.findViewById(R.id.sample_icon)).setImageResource(mImageResId);
280             ((TextView) view.findViewById(R.id.message)).setText(getManualTestInstruction());
281             return view;
282         }
283     }
284 }
285