am 8fd76dac: am 10aa4a47: Merge "Adding CTS and CTS Verifier for Heart Rate" into klp-modular-dev
* commit '8fd76dac965983fbc00d395c9d916d4ef35c1698':
Adding CTS and CTS Verifier for Heart Rate
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index b535384..2507955 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -27,6 +27,7 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.BODY_SENSORS"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
@@ -577,6 +578,18 @@
android:value="android.hardware.sensor.gyroscope"/>
</activity>
+ <activity android:name=".sensors.HeartRateMonitorTestActivity"
+ android:label="@string/snsr_heartrate_test"
+ android:screenOrientation="nosensor">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+ <meta-data android:name="test_required_features"
+ android:value="android.hardware.sensor.heartrate" />
+ </activity>
+
<!-- Disable the test until calibration routine is verified -->
<!--activity android:name=".sensors.MagneticFieldMeasurementTestActivity"
android:label="@string/snsr_mag_m_test"
diff --git a/apps/CtsVerifier/res/layout/snsr_hrm.xml b/apps/CtsVerifier/res/layout/snsr_hrm.xml
new file mode 100644
index 0000000..612b424
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_hrm.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <include android:id="@+id/pass_fail_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ layout="@layout/pass_fail_buttons" />
+
+ <TextView android:id="@+id/sensor_value"
+ android:background="@drawable/gray_bubble"
+ android:drawablePadding="10dip"
+ android:layout_above="@+id/pass_fail_buttons"
+ android:layout_centerInParent="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dip"
+ android:paddingLeft="10dip"
+ android:paddingRight="10dip"
+ android:paddingTop="5dip"
+ android:paddingBottom="5dip"
+ android:textSize="28dip"
+ />
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 00ff965..b6c846f 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -410,6 +410,12 @@
<string name="snsr_gyro_test_degrees_message">These values looks like degrees per second. These should be radians per second!</string>
<string name="snsr_gyro_m_test">Gyroscope Measurement Test</string>
+ <!-- Heart Rate -->
+ <string name="snsr_heartrate_test">Heart Rate Test</string>
+ <string name="snsr_heartrate_test_info">This test verifies that the heart rate monitor is working properly.\n\nVerify that the resting heart rate is between 0 and 100.</string>
+ <string name="snsr_heartrate_test_no_heartrate_title">No heart rate monitor?</string>
+ <string name="snsr_heartrate_test_no_heartrate_message">It doesn\'t seem like you have a heart rate monitor, so you don\'t need to run this test.</string>
+
<!-- Magnetic Field -->
<string name="snsr_mag_m_test">Magnetic Field Measurement Tests</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
index 6b87261..581121e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
@@ -188,6 +188,10 @@
new Feature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR, false),
};
+ public static final Feature[] ALL_KITKAT_WATCH_FEATURES = {
+ new Feature(PackageManager.FEATURE_SENSOR_HEART_RATE, false),
+ };
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -218,6 +222,9 @@
// add features from latest to last so that the latest requirements are put in the set first
int apiVersion = Build.VERSION.SDK_INT;
+ if (apiVersion >= Build.VERSION_CODES.KITKAT_WATCH) {
+ Collections.addAll(features, ALL_KITKAT_WATCH_FEATURES);
+ }
if (apiVersion >= Build.VERSION_CODES.KITKAT) {
Collections.addAll(features, ALL_KITKAT_FEATURES);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/HeartRateMonitorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/HeartRateMonitorTestActivity.java
new file mode 100644
index 0000000..d0cf41f
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/HeartRateMonitorTestActivity.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 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.AlertDialog;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+/**
+ * CTS Verifier case for verifying correct integration of heart rate monitor.
+ * If a user is wearing a device with an HRM, the value is between <> and <>
+ */
+public class HeartRateMonitorTestActivity extends PassFailButtons.Activity {
+ private SensorManager mSensorManager;
+ private Sensor mSensor;
+ private SensorListener mSensorListener;
+ private AlertDialog mNoHeartRateWarningDialog;
+ private TextView mSensorText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.snsr_hrm);
+ setInfoResources(R.string.snsr_heartrate_test, R.string.snsr_heartrate_test_info, 0);
+ setPassFailButtonClickListeners();
+
+ mSensorText = (TextView) findViewById(R.id.sensor_value);
+
+ mSensorManager = (SensorManager) getApplicationContext().getSystemService(
+ Context.SENSOR_SERVICE);
+ mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
+ mSensorListener = new SensorListener();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (!mSensorManager.registerListener(mSensorListener, mSensor,
+ SensorManager.SENSOR_DELAY_UI)) {
+ showNoHeartRateWarningDialog();
+ PassFailButtons.setTestResultAndFinish(this, getTestId(), getTestDetails(), true);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mSensorManager.unregisterListener(mSensorListener, mSensor);
+ }
+
+ private void showNoHeartRateWarningDialog() {
+ if (mNoHeartRateWarningDialog == null) {
+ mNoHeartRateWarningDialog = new AlertDialog.Builder(this)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle(R.string.snsr_heartrate_test_no_heartrate_title)
+ .setMessage(R.string.snsr_heartrate_test_no_heartrate_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .create();
+ }
+ if (!mNoHeartRateWarningDialog.isShowing()) {
+ mNoHeartRateWarningDialog.show();
+ }
+ }
+
+ private class SensorListener implements SensorEventListener {
+ private static final double MIN_HEART_RATE = 40;
+ private static final double MAX_HEART_RATE = 200;
+ @Override
+ public void onSensorChanged(SensorEvent sensorEvent) {
+ float value = sensorEvent.values[0];
+ if (value > MAX_HEART_RATE || value < MIN_HEART_RATE) {
+ updateWidgets(value, R.drawable.fs_error);
+ } else {
+ updateWidgets(value, R.drawable.fs_good);
+ }
+ }
+
+ void updateWidgets(float sensorValue, int icon) {
+ mSensorText.setText(String.format("%+.2f", sensorValue));
+ mSensorText.setCompoundDrawablesWithIntrinsicBounds(0, 0, icon, 0);
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int i) {
+
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
index 24dd368..907759f 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
@@ -99,6 +99,17 @@
assertNull(sensor);
}
+ sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
+ boolean hasHeartRate = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_SENSOR_HEART_RATE);
+ // heartrate sensor is optional
+ if (hasHeartRate) {
+ assertEquals(Sensor.TYPE_HEART_RATE, sensor.getType());
+ assertSensorValues(sensor);
+ } else {
+ assertNull(sensor);
+ }
+
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
boolean hasCompass = getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SENSOR_COMPASS);