blob: 628ff3e90c9fdf77c93142e65645370c44a456e1 [file] [log] [blame]
Rubin Xu55d22d42014-09-24 19:56:58 +01001/*
2 * Copyright (C) 2012 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
17package com.android.cts.verifier.managedprovisioning;
18
19import android.app.AlertDialog;
Rubin Xu55d22d42014-09-24 19:56:58 +010020import android.app.admin.DevicePolicyManager;
21import android.content.ActivityNotFoundException;
22import android.content.ComponentName;
23import android.content.Context;
24import android.content.DialogInterface;
25import android.content.Intent;
Rubin Xu55d22d42014-09-24 19:56:58 +010026import android.content.pm.PackageManager;
27import android.os.Bundle;
28import android.provider.Settings;
29import android.util.Log;
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +000030import android.view.LayoutInflater;
Rubin Xu55d22d42014-09-24 19:56:58 +010031import android.view.View;
32import android.view.ViewGroup;
33import android.view.View.OnClickListener;
34import android.widget.ArrayAdapter;
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +000035import android.widget.ImageView;
Rubin Xu55d22d42014-09-24 19:56:58 +010036import android.widget.ListView;
37import android.widget.TextView;
38import android.widget.Toast;
39
40import com.android.cts.verifier.PassFailButtons;
41import com.android.cts.verifier.R;
42import com.android.cts.verifier.TestListActivity;
43
44import java.util.ArrayList;
45import java.util.List;
46
47/**
48 * CTS verifier test for BYOD managed provisioning flow.
49 * This activity is responsible for starting the managed provisioning flow and verify the outcome of provisioning.
50 * It performs the following verifications:
51 * Full disk encryption is enabled.
52 * Profile owner is correctly installed.
53 * Profile owner shows up in the Settings app.
54 * Badged work apps show up in launcher.
55 * The first two verifications are performed automatically, by interacting with profile owner using
56 * cross-profile intents, while the last two are carried out manually by the user.
57 */
58public class ByodFlowTestActivity extends PassFailButtons.ListActivity {
59
60 private final String TAG = "ByodFlowTestActivity";
Sudheer Shanka98ff0002015-03-26 16:32:59 +000061 private static final int REQUEST_PROFILE_OWNER_STATUS = 1;
62 private static final int REQUEST_INTENT_FILTERS_STATUS = 2;
Rubin Xu55d22d42014-09-24 19:56:58 +010063
64 private ComponentName mAdminReceiverComponent;
65
Rubin Xuc2b00d82015-02-02 11:30:26 +000066 private TestAdapter mTestListAdapter;
Rubin Xu55d22d42014-09-24 19:56:58 +010067 private View mStartProvisioningButton;
68 private List<TestItem> mTests = new ArrayList<TestItem>();
69
70 protected DevicePolicyManager mDevicePolicyManager;
71
72 private TestItem mProfileOwnerInstalled;
Rubin Xuc2b00d82015-02-02 11:30:26 +000073 private TestItem mProfileAccountVisibleTest;
Rubin Xu55d22d42014-09-24 19:56:58 +010074 private TestItem mDeviceAdminVisibleTest;
75 private TestItem mWorkAppVisibleTest;
Alexandra Gherghinaaa24ed72014-10-08 01:11:32 +010076 private TestItem mCrossProfileIntentFiltersTest;
Robin Lee020f1852015-01-15 11:56:05 +000077 private TestItem mDisableNonMarketTest;
78 private TestItem mEnableNonMarketTest;
Alexandra Gherghina2c672b72015-01-22 11:20:23 +000079 private TestItem mWorkNotificationBadgedTest;
Rubin Xuc2b00d82015-02-02 11:30:26 +000080 private TestItem mAppSettingsVisibleTest;
81 private TestItem mLocationSettingsVisibleTest;
82 private TestItem mCredSettingsVisibleTest;
83 private TestItem mPrintSettingsVisibleTest;
Sudheer Shanka98ff0002015-03-26 16:32:59 +000084 private TestItem mIntentFiltersTest;
Rubin Xuc2b00d82015-02-02 11:30:26 +000085
86 private int mCurrentTestPosition;
Rubin Xu55d22d42014-09-24 19:56:58 +010087
88 @Override
89 protected void onCreate(Bundle savedInstanceState) {
90 super.onCreate(savedInstanceState);
91 mAdminReceiverComponent = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
92 mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
93 disableComponent();
94
95 setContentView(R.layout.provisioning_byod);
96 setInfoResources(R.string.provisioning_byod, R.string.provisioning_byod_info, -1);
97 setPassFailButtonClickListeners();
98 getPassButton().setEnabled(false);
99 setResult(RESULT_CANCELED);
100
101 setupTests();
102
Rubin Xuc2b00d82015-02-02 11:30:26 +0000103 mTestListAdapter = new TestAdapter(this);
104 setListAdapter(mTestListAdapter);
105 mTestListAdapter.addAll(mTests);
106
107 mCurrentTestPosition = 0;
Rubin Xu55d22d42014-09-24 19:56:58 +0100108
109 mStartProvisioningButton = findViewById(R.id.byod_start);
110 mStartProvisioningButton.setOnClickListener(new OnClickListener() {
111 @Override
112 public void onClick(View v) {
113 startByodProvisioning();
114 }
115 });
116
117 // If we are started by managed provisioning (fresh managed provisioning after encryption
118 // reboot), redirect the user back to the main test list. This is because the test result
119 // is only saved by the parent TestListActivity, and if we did allow the user to proceed
120 // here, the test result would be lost when this activity finishes.
121 if (ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS.equals(getIntent().getAction())) {
122 startActivity(new Intent(this, TestListActivity.class));
123 // Calling super.finish() because we delete managed profile in our overridden of finish(),
124 // which is not what we want to do here.
125 super.finish();
126 } else {
127 queryProfileOwner(false);
128 }
129 }
130
131 @Override
132 protected void onNewIntent(Intent intent) {
133 // This is called when managed provisioning completes successfully without reboot.
134 super.onNewIntent(intent);
135 if (ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS.equals(intent.getAction())) {
136 handleStatusUpdate(intent);
137 }
138 }
139
140 @Override
141 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Rubin Xu55d22d42014-09-24 19:56:58 +0100142 super.onActivityResult(requestCode, resultCode, data);
Sudheer Shanka98ff0002015-03-26 16:32:59 +0000143 // Called after queryProfileOwner()
144 if (requestCode == REQUEST_PROFILE_OWNER_STATUS && resultCode == RESULT_OK) {
Rubin Xu55d22d42014-09-24 19:56:58 +0100145 handleStatusUpdate(data);
Sudheer Shanka98ff0002015-03-26 16:32:59 +0000146 // Called after checkIntentFilters()
147 } else if (requestCode == REQUEST_INTENT_FILTERS_STATUS) {
148 handleIntentFiltersStatus(resultCode);
Rubin Xu55d22d42014-09-24 19:56:58 +0100149 }
150 }
151
152 private void handleStatusUpdate(Intent data) {
153 boolean provisioned = data.getBooleanExtra(ByodHelperActivity.EXTRA_PROVISIONED, false);
154 setTestResult(mProfileOwnerInstalled, provisioned ? TestResult.Passed : TestResult.Failed);
155 }
156
157 @Override
158 public void finish() {
159 // Pass and fail buttons are known to call finish() when clicked, and this is when we want to
160 // clean up the provisioned profile.
161 requestDeleteProfileOwner();
162 super.finish();
163 }
164
165 private void setupTests() {
166 mProfileOwnerInstalled = new TestItem(this, R.string.provisioning_byod_profileowner) {
167 @Override
168 public void performTest(ByodFlowTestActivity activity) {
169 queryProfileOwner(true);
170 }
171 };
172
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +0000173 /*
174 * To keep the image in this test up to date, use the instructions in
175 * {@link ByodIconSamplerActivity}.
176 */
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000177 mWorkAppVisibleTest = new TestItemWithIcon(this,
178 R.string.provisioning_byod_workapps_visible,
Rubin Xuc2b00d82015-02-02 11:30:26 +0000179 R.string.provisioning_byod_workapps_visible_instruction,
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000180 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),
181 R.drawable.badged_icon);
182
183 mWorkNotificationBadgedTest = new TestItemWithIcon(this,
184 R.string.provisioning_byod_work_notification,
185 R.string.provisioning_byod_work_notification_instruction,
186 new Intent(WorkNotificationTestActivity.ACTION_WORK_NOTIFICATION),
187 R.drawable.ic_corp_icon);
Rubin Xu55d22d42014-09-24 19:56:58 +0100188
Robin Lee020f1852015-01-15 11:56:05 +0000189 mDisableNonMarketTest = new TestItem(this, R.string.provisioning_byod_nonmarket_deny,
190 R.string.provisioning_byod_nonmarket_deny_info,
191 new Intent(ByodHelperActivity.ACTION_INSTALL_APK)
192 .putExtra(ByodHelperActivity.EXTRA_ALLOW_NON_MARKET_APPS, false));
193
194 mEnableNonMarketTest = new TestItem(this, R.string.provisioning_byod_nonmarket_allow,
195 R.string.provisioning_byod_nonmarket_allow_info,
196 new Intent(ByodHelperActivity.ACTION_INSTALL_APK)
197 .putExtra(ByodHelperActivity.EXTRA_ALLOW_NON_MARKET_APPS, true));
198
Rubin Xuc2b00d82015-02-02 11:30:26 +0000199 mProfileAccountVisibleTest = new TestItem(this, R.string.provisioning_byod_profile_visible,
200 R.string.provisioning_byod_profile_visible_instruction,
201 new Intent(Settings.ACTION_SETTINGS));
202
203 mAppSettingsVisibleTest = new TestItem(this, R.string.provisioning_byod_app_settings,
204 R.string.provisioning_byod_app_settings_instruction,
205 new Intent(Settings.ACTION_APPLICATION_SETTINGS));
206
207 mDeviceAdminVisibleTest = new TestItem(this, R.string.provisioning_byod_admin_visible,
208 R.string.provisioning_byod_admin_visible_instruction,
209 new Intent(Settings.ACTION_SECURITY_SETTINGS));
210
211 mCredSettingsVisibleTest = new TestItem(this, R.string.provisioning_byod_cred_settings,
212 R.string.provisioning_byod_cred_settings_instruction,
213 new Intent(Settings.ACTION_SECURITY_SETTINGS));
214
215 mLocationSettingsVisibleTest = new TestItem(this,
216 R.string.provisioning_byod_location_settings,
217 R.string.provisioning_byod_location_settings_instruction,
218 new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
219
220 mPrintSettingsVisibleTest = new TestItem(this, R.string.provisioning_byod_print_settings,
221 R.string.provisioning_byod_print_settings_instruction,
222 new Intent(Settings.ACTION_PRINT_SETTINGS));
223
Alexandra Gherghinaaa24ed72014-10-08 01:11:32 +0100224 Intent intent = new Intent(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
Rubin Xuc2b00d82015-02-02 11:30:26 +0000225 Intent chooser = Intent.createChooser(intent,
226 getResources().getString(R.string.provisioning_cross_profile_chooser));
Alexandra Gherghinaaa24ed72014-10-08 01:11:32 +0100227 mCrossProfileIntentFiltersTest = new TestItem(this,
228 R.string.provisioning_byod_cross_profile,
229 R.string.provisioning_byod_cross_profile_instruction,
230 chooser);
231
Sudheer Shanka98ff0002015-03-26 16:32:59 +0000232 // Test for checking if the required intent filters are set during managed provisioning.
233 mIntentFiltersTest = new TestItem(this,
234 R.string.provisioning_byod_cross_profile_intent_filters) {
235 @Override
236 public void performTest(ByodFlowTestActivity activity) {
237 checkIntentFilters();
238 }
239 };
240
Rubin Xu55d22d42014-09-24 19:56:58 +0100241 mTests.add(mProfileOwnerInstalled);
Rubin Xuc2b00d82015-02-02 11:30:26 +0000242
243 // Badge related tests
Rubin Xu55d22d42014-09-24 19:56:58 +0100244 mTests.add(mWorkAppVisibleTest);
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000245 mTests.add(mWorkNotificationBadgedTest);
Rubin Xuc2b00d82015-02-02 11:30:26 +0000246
247 // Settings related tests.
248 mTests.add(mProfileAccountVisibleTest);
249 mTests.add(mDeviceAdminVisibleTest);
250 mTests.add(mCredSettingsVisibleTest);
251 mTests.add(mAppSettingsVisibleTest);
252 mTests.add(mLocationSettingsVisibleTest);
253 mTests.add(mPrintSettingsVisibleTest);
254
Alexandra Gherghinaaa24ed72014-10-08 01:11:32 +0100255 mTests.add(mCrossProfileIntentFiltersTest);
Robin Lee020f1852015-01-15 11:56:05 +0000256 mTests.add(mDisableNonMarketTest);
257 mTests.add(mEnableNonMarketTest);
Sudheer Shanka98ff0002015-03-26 16:32:59 +0000258 mTests.add(mIntentFiltersTest);
Rubin Xu55d22d42014-09-24 19:56:58 +0100259 }
260
261 @Override
262 protected void onListItemClick(ListView l, View v, int position, long id) {
263 super.onListItemClick(l, v, position, id);
Rubin Xuc2b00d82015-02-02 11:30:26 +0000264 mCurrentTestPosition = position;
Rubin Xu55d22d42014-09-24 19:56:58 +0100265 TestItem test = (TestItem) getListAdapter().getItem(position);
266 test.performTest(this);
267 }
268
269 private void showManualTestDialog(final TestItem test) {
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +0000270 AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this)
Rubin Xu55d22d42014-09-24 19:56:58 +0100271 .setIcon(android.R.drawable.ic_dialog_info)
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +0000272 .setTitle(R.string.provisioning_byod)
Rubin Xu55d22d42014-09-24 19:56:58 +0100273 .setNeutralButton(R.string.provisioning_byod_go, null)
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +0000274 .setPositiveButton(R.string.pass_button_text, new AlertDialog.OnClickListener() {
Rubin Xu55d22d42014-09-24 19:56:58 +0100275 @Override
276 public void onClick(DialogInterface dialog, int which) {
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000277 clearRemainingState(test);
Rubin Xu55d22d42014-09-24 19:56:58 +0100278 setTestResult(test, TestResult.Passed);
279 }
280 })
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +0000281 .setNegativeButton(R.string.fail_button_text, new AlertDialog.OnClickListener() {
Rubin Xu55d22d42014-09-24 19:56:58 +0100282 @Override
283 public void onClick(DialogInterface dialog, int which) {
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000284 clearRemainingState(test);
Rubin Xu55d22d42014-09-24 19:56:58 +0100285 setTestResult(test, TestResult.Failed);
286 }
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +0000287 });
288 View customView = test.getCustomView();
289 if (customView != null) {
290 dialogBuilder.setView(customView);
291 } else {
292 dialogBuilder.setMessage(test.getManualTestInstruction());
293 }
Rubin Xuc2b00d82015-02-02 11:30:26 +0000294 final AlertDialog dialog = dialogBuilder.show();
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +0000295 // Note: Setting the OnClickListener on the Dialog rather than the Builder, prevents the
296 // dialog being dismissed on onClick.
Rubin Xu55d22d42014-09-24 19:56:58 +0100297 dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() {
298 @Override
299 public void onClick(View v) {
Rubin Xuc2b00d82015-02-02 11:30:26 +0000300 try {
301 ByodFlowTestActivity.this.startActivity(test.getManualTestIntent());
302 } catch (ActivityNotFoundException e) {
303 Toast.makeText(ByodFlowTestActivity.this,
304 "Cannot start " + test.getManualTestIntent(), Toast.LENGTH_LONG).show();
305 setTestResult(test, TestResult.Failed);
306 dialog.dismiss();
307 }
Rubin Xu55d22d42014-09-24 19:56:58 +0100308 }
309 });
310 }
311
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000312 private void clearRemainingState(final TestItem test) {
313 if (WorkNotificationTestActivity.ACTION_WORK_NOTIFICATION.equals(
314 test.getManualTestIntent().getAction())) {
Rubin Xuc2b00d82015-02-02 11:30:26 +0000315 try {
316 ByodFlowTestActivity.this.startActivity(new Intent(
317 WorkNotificationTestActivity.ACTION_CLEAR_WORK_NOTIFICATION));
318 } catch (ActivityNotFoundException e) {
319 // User shouldn't run this test before work profile is set up.
320 }
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000321 }
322 }
323
Rubin Xu55d22d42014-09-24 19:56:58 +0100324 private void setTestResult(TestItem test, TestResult result) {
325 test.setPassFailState(result);
326
327 boolean testSucceeds = true;
328 for(TestItem aTest : mTests) {
329 testSucceeds &= (aTest.getPassFailState() == TestResult.Passed);
330 }
331 getPassButton().setEnabled(testSucceeds);
Rubin Xuc2b00d82015-02-02 11:30:26 +0000332 mTestListAdapter.notifyDataSetChanged();
333
334 this.getListView().smoothScrollToPosition(mCurrentTestPosition + 1);
Rubin Xu55d22d42014-09-24 19:56:58 +0100335 }
336
337 private void startByodProvisioning() {
338 Intent sending = new Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
Sudheer Shankab64e0dc2015-03-23 16:42:35 +0000339 sending.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
340 mAdminReceiverComponent);
Rubin Xu55d22d42014-09-24 19:56:58 +0100341
342 if (sending.resolveActivity(getPackageManager()) != null) {
343 // ManagedProvisioning must be started with startActivityForResult, but we don't
344 // care about the result, so passing 0 as a requestCode
345 startActivityForResult(sending, 0);
346 } else {
347 showToast(R.string.provisioning_byod_disabled);
348 }
349 }
350
351 private void queryProfileOwner(boolean showToast) {
352 try {
353 Intent intent = new Intent(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
Sudheer Shanka98ff0002015-03-26 16:32:59 +0000354 startActivityForResult(intent, REQUEST_PROFILE_OWNER_STATUS);
Rubin Xu55d22d42014-09-24 19:56:58 +0100355 }
356 catch (ActivityNotFoundException e) {
357 Log.d(TAG, "queryProfileOwner: ActivityNotFoundException", e);
358 setTestResult(mProfileOwnerInstalled, TestResult.Failed);
359 if (showToast) {
360 showToast(R.string.provisioning_byod_no_activity);
361 }
362 }
363 }
364
365 private void requestDeleteProfileOwner() {
366 try {
367 Intent intent = new Intent(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
368 startActivity(intent);
369 showToast(R.string.provisioning_byod_delete_profile);
370 }
371 catch (ActivityNotFoundException e) {
372 Log.d(TAG, "requestDeleteProfileOwner: ActivityNotFoundException", e);
373 }
374 }
375
Sudheer Shanka98ff0002015-03-26 16:32:59 +0000376 private void checkIntentFilters() {
377 try {
378 // We disable the ByodHelperActivity in the primary profile. So, this intent
379 // will be handled by the ByodHelperActivity in the managed profile.
380 Intent intent = new Intent(ByodHelperActivity.ACTION_CHECK_INTENT_FILTERS);
381 startActivityForResult(intent, REQUEST_INTENT_FILTERS_STATUS);
382 } catch (ActivityNotFoundException e) {
383 Log.d(TAG, "checkIntentFilters: ActivityNotFoundException", e);
384 setTestResult(mIntentFiltersTest, TestResult.Failed);
385 showToast(R.string.provisioning_byod_no_activity);
386 }
387 }
388
389 private void handleIntentFiltersStatus(int resultCode) {
390 // we use the resultCode from ByodHelperActivity in the managed profile to know if certain
391 // intents fired from the managed profile are forwarded.
392 final boolean intentFiltersSetForManagedIntents = (resultCode == RESULT_OK);
393 // Since the ByodFlowTestActivity is running in the primary profile, we directly use
394 // the IntentFiltersTestHelper to know if certain intents fired from the primary profile
395 // are forwarded.
396 final boolean intentFiltersSetForPrimaryIntents =
397 new IntentFiltersTestHelper(this).checkCrossProfileIntentFilters(
398 IntentFiltersTestHelper.FLAG_INTENTS_FROM_PRIMARY);
399 final boolean intentFiltersSet =
400 intentFiltersSetForPrimaryIntents & intentFiltersSetForManagedIntents;
401 setTestResult(mIntentFiltersTest,
402 intentFiltersSet ? TestResult.Passed : TestResult.Failed);
403 }
404
Rubin Xu55d22d42014-09-24 19:56:58 +0100405 private void disableComponent() {
406 // Disable app components in the current profile, so only the counterpart in the other profile
407 // can respond (via cross-profile intent filter)
408 getPackageManager().setComponentEnabledSetting(new ComponentName(
409 this, ByodHelperActivity.class),
410 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
411 PackageManager.DONT_KILL_APP);
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000412 getPackageManager().setComponentEnabledSetting(new ComponentName(
413 this, WorkNotificationTestActivity.class),
414 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
415 PackageManager.DONT_KILL_APP);
Rubin Xu55d22d42014-09-24 19:56:58 +0100416 }
417
Rubin Xu55d22d42014-09-24 19:56:58 +0100418 private void showToast(int messageId) {
419 String message = getString(messageId);
420 Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
421 }
422
423 enum TestResult {
424 Unknown, Failed, Passed
425 }
426
427 static class TestItem {
428
429 private String mDisplayName;
430 private TestResult mPassed;
431 private boolean mManualTest;
432 private String mManualInstruction;
433 private Intent mManualIntent;
434
435 public TestItem(Context context, int nameResId) {
436 mDisplayName = context.getString(nameResId);
437 mPassed = TestResult.Unknown;
438 mManualTest = false;
439 }
440
441 public void performTest(ByodFlowTestActivity activity) {
442 if (isManualTest()) {
443 activity.showManualTestDialog(this);
444 }
445 }
446
447 public TestItem(Context context, int nameResId, int testInstructionResId, Intent testIntent) {
448 mDisplayName = context.getString(nameResId);
449 mPassed = TestResult.Unknown;
450 mManualTest = true;
451 mManualInstruction = context.getString(testInstructionResId);
452 mManualIntent = testIntent;
453 }
454
455 @Override
456 public String toString() {
457 return mDisplayName;
458 }
459
460 TestResult getPassFailState() {
461 return mPassed;
462 }
463
464 void setPassFailState(TestResult state) {
465 mPassed = state;
466 }
467
468 public boolean isManualTest() {
469 return mManualTest;
470 }
471
472 public String getManualTestInstruction() {
473 return mManualInstruction;
474 }
475
476 public Intent getManualTestIntent() {
477 return mManualIntent;
478 }
Alexandra Gherghina9c1c5a52014-12-09 12:55:23 +0000479
480 public View getCustomView() {
481 return null;
482 }
Rubin Xu55d22d42014-09-24 19:56:58 +0100483 }
484
Alexandra Gherghina2c672b72015-01-22 11:20:23 +0000485 static class TestItemWithIcon extends TestItem {
486
487 private int mImageResId;
488 private Context mContext;
489
490 public TestItemWithIcon(Context context, int nameResId, int testInstructionResId,
491 Intent testIntent, int imageResId) {
492 super(context, nameResId, testInstructionResId, testIntent);
493 mContext = context;
494 mImageResId = imageResId;
495 }
496
497 @Override
498 public View getCustomView() {
499 LayoutInflater layoutInflater = LayoutInflater.from(mContext);
500 View view = layoutInflater.inflate(R.layout.byod_custom_view,
501 null /* root */);
502 ((ImageView) view.findViewById(R.id.sample_icon)).setImageResource(mImageResId);
503 ((TextView) view.findViewById(R.id.message)).setText(getManualTestInstruction());
504 return view;
505 }
506 }
507
Rubin Xu55d22d42014-09-24 19:56:58 +0100508 static class TestAdapter extends ArrayAdapter<TestItem> {
509
510 public TestAdapter(Context context) {
511 super(context, android.R.layout.simple_list_item_1);
512 }
513
514 @Override
515 public View getView(int position, View convertView, ViewGroup parent) {
516 TextView view = (TextView) super.getView(position, convertView, parent);
517
518 TestItem item = getItem(position);
519 int backgroundResource = 0;
520 int iconResource = 0;
521 if (item.getPassFailState() == TestResult.Passed) {
522 backgroundResource = R.drawable.test_pass_gradient;
523 iconResource = R.drawable.fs_good;
524 } else if (item.getPassFailState() == TestResult.Failed){
525 backgroundResource = R.drawable.test_fail_gradient;
526 iconResource = R.drawable.fs_error;
527 }
528 view.setBackgroundResource(backgroundResource);
529 view.setPadding(10, 0, 10, 0);
530 view.setCompoundDrawablePadding(10);
531 view.setCompoundDrawablesWithIntrinsicBounds(0, 0, iconResource, 0);
532
533 return view;
534 }
535 }
Rubin Xu55d22d42014-09-24 19:56:58 +0100536}