blob: 9f4b2b2447473c8fa32de326886cb80859117829 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.cts.verifier.sensors;
import android.app.Activity;
import android.graphics.Color;
import android.hardware.cts.helpers.SensorNotSupportedException;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.method.ScrollingMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.widget.TextView;
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestResult;
import java.security.InvalidParameterException;
import java.util.concurrent.Semaphore;
/**
* Base class to author Sensor semi-automated test cases.
* These tests can only wait for operators to notify at some intervals, but the test needs to be
* autonomous to verify the data collected.
*/
public abstract class BaseSensorSemiAutomatedTestActivity
extends Activity
implements View.OnClickListener, Runnable {
protected final String LOG_TAG = "TestRunner";
private final Semaphore mSemaphore = new Semaphore(0);
private TextView mLogView;
private View mNextView;
private Thread mWorkerThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.snsr_semi_auto_test);
}
@Override
public void onStart() {
super.onStart();
mLogView = (TextView) this.findViewById(R.id.log_text);
mNextView = this.findViewById(R.id.next_button);
mNextView.setOnClickListener(this);
mLogView.setMovementMethod(new ScrollingMovementMethod());
updateButton(false /*enabled*/);
mWorkerThread = new Thread(this);
mWorkerThread.start();
}
@Override
public void onClick(View target) {
mSemaphore.release();
}
@Override
public void run() {
String message = "";
SensorTestResult testResult = SensorTestResult.PASS;
try {
onRun();
} catch(SensorNotSupportedException e) {
// the sensor is not supported/available in the device, log a warning and skip the test
testResult = SensorTestResult.SKIPPED;
message = e.getMessage();
} catch(Throwable e) {
testResult = SensorTestResult.FAIL;
message = e.getMessage();
}
setTestResult(testResult, message);
appendText("\nTest completed. Press 'Next' to finish.\n");
waitForUser();
finish();
}
/**
* This is the method that subclasses will implement to define the operations that need to be
* verified.
* Any exception thrown will cause the test to fail, additionally mAssert can be used to verify
* the tests state.
*
* throws Throwable
*/
protected abstract void onRun() throws Throwable;
/**
* Helper methods for subclasses to interact with the UI and the operator.
*/
protected void appendText(String text, int textColor) {
this.runOnUiThread(new TextAppender(mLogView, text, textColor));
}
protected void appendText(String text) {
this.runOnUiThread(new TextAppender(mLogView, text));
}
protected void updateButton(boolean enabled) {
this.runOnUiThread(new ButtonEnabler(this.mNextView, enabled));
}
protected void waitForUser() {
updateButton(true);
try {
mSemaphore.acquire();
} catch(InterruptedException e) {}
updateButton(false);
}
protected void logSuccess() {
appendText("PASS", Color.GREEN);
}
protected void playSound() {
MediaPlayer player = MediaPlayer.create(this, Settings.System.DEFAULT_NOTIFICATION_URI);
player.start();
try {
Thread.sleep(500);
} catch(InterruptedException e) {
} finally {
player.stop();
}
}
/**
* Private methods.
*/
private String getTestId() {
return this.getClass().getName();
}
private void setTestResult(SensorTestResult testResult, String message) {
int textColor;
switch(testResult) {
case SKIPPED:
textColor = Color.YELLOW;
TestResult.setPassedResult(this, this.getTestId(), message);
break;
case PASS:
textColor = Color.GREEN;
TestResult.setPassedResult(this, this.getTestId(), message);
break;
case FAIL:
textColor = Color.RED;
TestResult.setFailedResult(this, this.getTestId(), message);
break;
default:
throw new InvalidParameterException("Unrecognized testResult.");
}
appendText(message, textColor);
}
private enum SensorTestResult {
SKIPPED,
PASS,
FAIL
}
private class TextAppender implements Runnable {
private final TextView mTextView;
private final SpannableStringBuilder mMessageBuilder;
public TextAppender(TextView textView, String message, int textColor) {
mTextView = textView;
mMessageBuilder = new SpannableStringBuilder(message + "\n");
ForegroundColorSpan colorSpan = new ForegroundColorSpan(textColor);
mMessageBuilder.setSpan(
colorSpan,
0 /*start*/,
message.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
public TextAppender(TextView textView, String message) {
this(textView, message, textView.getCurrentTextColor());
}
@Override
public void run() {
mTextView.append(mMessageBuilder);
}
}
private class ButtonEnabler implements Runnable {
private final View mButtonView;
private final boolean mButtonEnabled;
public ButtonEnabler(View buttonView, boolean buttonEnabled) {
mButtonView = buttonView;
mButtonEnabled = buttonEnabled;
}
@Override
public void run() {
mButtonView.setEnabled(mButtonEnabled);
}
}
}