Add CTS-V test for Battery Saver UI affordance.
This is for CDD requirement 8.3/ H-1-1.
Bug: 123045487
Test: install on device and manually check activities
Change-Id: I6947c57c24abf38623ff2207f688966a07e8011e
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 08f52f1..167248d 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -156,6 +156,17 @@
android:theme="@style/OverlayTheme"
android:label="Overlaying Activity"/>
+ <activity
+ android:name=".battery.BatterySaverTestActivity"
+ android:label="@string/battery_saver_test"
+ android:configChanges="keyboardHidden|orientation|screenSize">
+ <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_other" />
+ </activity>
+
<activity android:name=".forcestop.RecentTaskRemovalTestActivity"
android:label="@string/remove_from_recents_test"
android:configChanges="keyboardHidden|orientation|screenSize">
diff --git a/apps/CtsVerifier/res/layout/ordered_test.xml b/apps/CtsVerifier/res/layout/ordered_test.xml
new file mode 100644
index 0000000..1c0b029
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/ordered_test.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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">
+
+ <TextView
+ android:id="@+id/txt_instruction"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/InstructionsSmallFont"
+ android:layout_alignParentTop="true" />
+
+ <Button
+ android:id="@+id/btn_next"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/next_button_text"
+ android:layout_below="@id/txt_instruction" />
+
+ <include android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ layout="@layout/pass_fail_buttons" />
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/screen_pinning.xml b/apps/CtsVerifier/res/layout/screen_pinning.xml
deleted file mode 100644
index f1d7b65..0000000
--- a/apps/CtsVerifier/res/layout/screen_pinning.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?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" >
-
- <TextView
- android:id="@+id/error_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <ScrollView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true" >
-
- <RelativeLayout
- android:id="@+id/instructions_group"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
-
- <LinearLayout
- android:id="@+id/instructions_list"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
-
- </LinearLayout>
-
- <Button
- android:id="@+id/next_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_below="@id/instructions_list"
- android:text="@string/next_button_text" />
-
- </RelativeLayout>
- </ScrollView>
-
- <include
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons" />
-
-</RelativeLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 4b9afec..64930a0 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -23,6 +23,7 @@
<string name="fail_button_text">Fail</string>
<string name="next_button_text">Next</string>
<string name="go_button_text">Go</string>
+ <string name="tests_completed_successfully">All tests completed successfully.</string>
<!-- Strings for TestListActivity -->
<string name="test_category_audio">Audio</string>
@@ -70,6 +71,35 @@
<string name="bu_generate_error">Error occurred while generating test data...</string>
<string name="bu_settings">Settings</string>
+ <!-- Strings for BatterySaverTestActivity -->
+ <string name="battery_saver_test">Battery Saver Test</string>
+ <string name="battery_saver_test_info">
+ This test verifies that the device provides a user affordance to enable and disable
+ Battery Saver feature.
+ </string>
+ <string name="battery_saver_test_no_battery_detected">
+ No battery detected. This test will only work on devices that contain a battery.
+ </string>
+ <string name="battery_saver_test_unplug">
+ Unplug the device or run \"adb shell dumpsys battery unplug\".
+ </string>
+ <string name="battery_saver_test_device_plugged_in">
+ The device is still plugged in.
+ </string>
+ <string name="battery_saver_test_enable_bs">
+ Look for a button that allows you to turn Battery Saver on and off. The button may be in the
+ Quick Settings section or on the Battery page of device settings. Use the button to turn
+ Battery Saver on.
+ </string>
+ <string name="battery_saver_test_disable_bs">
+ Now use the button to turn Battery Saver off.
+ </string>
+ <string name="battery_saver_test_start_turn_bs_off">
+ Turn Battery Saver off to begin the test.
+ </string>
+ <string name="battery_saver_test_bs_on">Battery Saver is on.</string>
+ <string name="battery_saver_test_bs_off">Battery Saver is off.</string>
+
<!-- Strings for Device Administration tests -->
<string name="da_policy_serialization_test">Policy Serialization Test</string>
<string name="da_policy_serialization_info">This test checks that a device policy is properly
@@ -4346,7 +4376,6 @@
<string name="screen_pin_check_pinned">Press Next to verify the app is pinned.</string>
<string name="screen_pin_no_exit">Try to leave the app without unpinning the screen. Press next once you have verified you cannot leave.</string>
<string name="screen_pin_exit">Use interactions defined by your device to unpin such as long pressing the back and overview button, then press next.</string>
- <string name="screen_pinning_done">All tests completed successfully.</string>
<string name="error_screen_no_longer_pinned">The screen was no longer pinned.</string>
<string name="error_screen_already_pinned">Cannot start the test with the screen already pinned.</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/OrderedTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/OrderedTestActivity.java
new file mode 100644
index 0000000..d24fdb7
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/OrderedTestActivity.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 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;
+
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * {@link PassFailButtons.Activity} that supports showing a series of tests in order.
+ */
+public abstract class OrderedTestActivity extends PassFailButtons.Activity {
+ private static final String KEY_CURRENT_TEST = "current_test";
+
+ private Test[] mTests;
+ private int mTestIndex;
+
+ private Button mNextButton;
+ private TextView mInstructions;
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.ordered_test);
+ setPassFailButtonClickListeners();
+
+ mTests = getTests();
+
+ mInstructions = findViewById(R.id.txt_instruction);
+
+ mNextButton = findViewById(R.id.btn_next);
+ mNextButton.setOnClickListener(v -> {
+ if ((mTestIndex >= 0) && (mTestIndex < mTests.length)) {
+ mTests[mTestIndex].onNextClick();
+ }
+ });
+
+ // Don't allow pass until all tests complete.
+ findViewById(R.id.pass_button).setVisibility(View.GONE);
+
+ // Figure out if we are in a test or starting from the beginning.
+ if (savedInstanceState != null && savedInstanceState.containsKey(KEY_CURRENT_TEST)) {
+ mTestIndex = savedInstanceState.getInt(KEY_CURRENT_TEST);
+ } else {
+ mTestIndex = 0;
+ }
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+
+ mTests[mTestIndex].run();
+ }
+
+ /** Returns a list of tests to run in order. */
+ protected abstract Test[] getTests();
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ outState.putInt(KEY_CURRENT_TEST, mTestIndex);
+ }
+
+ protected void succeed() {
+ runOnUiThread(() -> {
+ mTestIndex++;
+ if (mTestIndex < mTests.length) {
+ mTests[mTestIndex].run();
+ } else {
+ // On test completion, hide "next" and "fail" buttons, and show "pass" button
+ // instead.
+ mInstructions.setText(R.string.tests_completed_successfully);
+ mNextButton.setVisibility(View.GONE);
+ findViewById(R.id.pass_button).setVisibility(View.VISIBLE);
+ findViewById(R.id.fail_button).setVisibility(View.GONE);
+ }
+ });
+ }
+
+ protected void error(int stringResId) {
+ Toast.makeText(this, stringResId, Toast.LENGTH_SHORT).show();
+ }
+
+ protected abstract class Test {
+ private final int mStringId;
+
+ public Test(int stringResId) {
+ mStringId = stringResId;
+ }
+
+ protected void run() {
+ showText();
+ }
+
+ protected void showText() {
+ if (mStringId == 0) {
+ return;
+ }
+ mInstructions.setText(mStringId);
+ }
+
+ protected void onNextClick() {
+ }
+ }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/battery/BatterySaverTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/battery/BatterySaverTestActivity.java
new file mode 100644
index 0000000..f0dc540
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/battery/BatterySaverTestActivity.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 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.battery;
+
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.view.View;
+
+import com.android.cts.verifier.OrderedTestActivity;
+import com.android.cts.verifier.R;
+
+public class BatterySaverTestActivity extends OrderedTestActivity {
+ private PowerManager mPowerManager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setInfoResources(R.string.battery_saver_test, R.string.battery_saver_test_info, -1);
+
+ mPowerManager = getSystemService(PowerManager.class);
+ }
+
+ @Override
+ protected OrderedTestActivity.Test[] getTests() {
+ return new Test[]{
+ // Confirm a battery exists before proceeding with the rest of the tests,
+ mConfirmBatteryExists,
+ // Verify device is unplugged.
+ mConfirmUnplugged,
+ // Verify battery saver is off.
+ mConfirmBsOff,
+ mEnableBs,
+ mDisableBs
+ };
+ }
+
+ private final Test mConfirmBatteryExists = new Test(
+ R.string.battery_saver_test_no_battery_detected) {
+ @Override
+ protected void run() {
+ super.run();
+
+ final Intent batteryInfo = registerReceiver(null, new
+ IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+
+ if (batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true)) {
+ succeed();
+ } else {
+ findViewById(R.id.btn_next).setVisibility(View.GONE);
+ // Set both pass and fail to visible in case the device is meant to have a battery.
+ findViewById(R.id.pass_button).setVisibility(View.VISIBLE);
+ findViewById(R.id.fail_button).setVisibility(View.VISIBLE);
+ }
+ }
+ };
+
+ private final Test mConfirmUnplugged = new Test(R.string.battery_saver_test_unplug) {
+ @Override
+ protected void run() {
+ super.run();
+
+ if (!isPluggedIn()) {
+ succeed();
+ }
+ }
+
+ @Override
+ protected void onNextClick() {
+ if (isPluggedIn()) {
+ error(R.string.battery_saver_test_device_plugged_in);
+ } else {
+ succeed();
+ }
+ }
+
+ private boolean isPluggedIn() {
+ Intent intent = registerReceiver(null,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+ return plugged == BatteryManager.BATTERY_PLUGGED_AC
+ || plugged == BatteryManager.BATTERY_PLUGGED_USB
+ || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
+ }
+ };
+
+ private final Test mConfirmBsOff = new Test(R.string.battery_saver_test_start_turn_bs_off) {
+ @Override
+ protected void run() {
+ super.run();
+
+ if (!mPowerManager.isPowerSaveMode()) {
+ succeed();
+ }
+ }
+
+ @Override
+ protected void onNextClick() {
+ if (mPowerManager.isPowerSaveMode()) {
+ error(R.string.battery_saver_test_bs_on);
+ } else {
+ succeed();
+ }
+ }
+ };
+
+ private final Test mEnableBs = new Test(R.string.battery_saver_test_enable_bs) {
+ @Override
+ protected void onNextClick() {
+ if (mPowerManager.isPowerSaveMode()) {
+ succeed();
+ } else {
+ error(R.string.battery_saver_test_bs_off);
+ }
+ }
+ };
+
+ private final Test mDisableBs = new Test(R.string.battery_saver_test_disable_bs) {
+ @Override
+ protected void onNextClick() {
+ if (!mPowerManager.isPowerSaveMode()) {
+ succeed();
+ } else {
+ error(R.string.battery_saver_test_bs_on);
+ }
+ }
+ };
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
index a6e5f98..180306e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
@@ -18,78 +18,40 @@
import android.app.ActivityManager;
import android.os.Bundle;
import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.OrderedTestActivity;
import com.android.cts.verifier.R;
-public class ScreenPinningTestActivity extends PassFailButtons.Activity {
+public class ScreenPinningTestActivity extends OrderedTestActivity {
private static final String TAG = "ScreenPinningTestActivity";
- private static final String KEY_CURRENT_TEST = "keyCurrentTest";
private static final long TASK_MODE_CHECK_DELAY = 200;
private static final int MAX_TASK_MODE_CHECK_COUNT = 5;
- private Test[] mTests;
- private int mTestIndex;
-
private ActivityManager mActivityManager;
- private Button mNextButton;
- private LinearLayout mInstructions;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.screen_pinning);
- setPassFailButtonClickListeners();
-
- mTests = new Test[] {
- // Verify not already pinned.
- mCheckStartedUnpinned,
- // Enter pinning, verify pinned, try leaving and have the user exit.
- mCheckStartPinning,
- mCheckIsPinned,
- mCheckTryLeave,
- mCheckUnpin,
- // Enter pinning, verify pinned, and use APIs to exit.
- mCheckStartPinning,
- mCheckIsPinned,
- mCheckUnpinFromCode,
- // All done.
- mDone,
- };
mActivityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
- mInstructions = (LinearLayout) findViewById(R.id.instructions_list);
-
- mNextButton = (Button) findViewById(R.id.next_button);
- mNextButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if ((mTestIndex >= 0) && (mTestIndex < mTests.length)) {
- mTests[mTestIndex].onNextClick();
- }
- }
- });
-
- // Don't allow pass until all tests complete.
- findViewById(R.id.pass_button).setVisibility(View.GONE);
-
- // Figure out if we are in a test or starting from the beginning.
- if (savedInstanceState != null && savedInstanceState.containsKey(KEY_CURRENT_TEST)) {
- mTestIndex = savedInstanceState.getInt(KEY_CURRENT_TEST);
- } else {
- mTestIndex = 0;
- }
- mTests[mTestIndex].run();
- };
+ }
@Override
- protected void onSaveInstanceState(Bundle outState) {
- outState.putInt(KEY_CURRENT_TEST, mTestIndex);
+ protected Test[] getTests() {
+ return new Test[]{
+ // Verify not already pinned.
+ mCheckStartedUnpinned,
+ // Enter pinning, verify pinned, try leaving and have the user exit.
+ mCheckStartPinning,
+ mCheckIsPinned,
+ mCheckTryLeave,
+ mCheckUnpin,
+ // Enter pinning, verify pinned, and use APIs to exit.
+ mCheckStartPinning,
+ mCheckIsPinned,
+ mCheckUnpinFromCode
+ };
}
@Override
@@ -98,27 +60,8 @@
// Users can still leave by pressing fail (or when done the pass) button.
}
- private void show(int id) {
- TextView tv = new TextView(this);
- tv.setPadding(10, 10, 10, 30);
- tv.setText(id);
- mInstructions.removeAllViews();
- mInstructions.addView(tv);
- }
-
- private void succeed() {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mTestIndex++;
- if (mTestIndex < mTests.length) {
- mTests[mTestIndex].run();
- }
- }
- });
- }
-
- private void error(int errorId) {
+ @Override
+ protected void error(int errorId) {
error(errorId, new Throwable());
}
@@ -128,10 +71,8 @@
public void run() {
String error = getString(errorId);
Log.d(TAG, error, cause);
- // No more instructions needed.
- findViewById(R.id.instructions_group).setVisibility(View.GONE);
- ((TextView) findViewById(R.id.error_text)).setText(error);
+ ((TextView) findViewById(R.id.txt_instruction)).setText(error);
}
});
}
@@ -211,40 +152,6 @@
error(R.string.error_screen_pinning_couldnt_exit);
}
}
- };
+ }
};
-
- private final Test mDone = new Test(R.string.screen_pinning_done) {
- @Override
- protected void run() {
- super.run();
- // On test completion, hide "next" button, and show "pass" button
- // instead.
- mNextButton.setVisibility(View.GONE);
- findViewById(R.id.pass_button).setVisibility(View.VISIBLE);
- };
- };
-
- private abstract class Test {
- private final int mResId;
-
- public Test(int showId) {
- mResId = showId;
- }
-
- protected void run() {
- showText();
- }
-
- public void showText() {
- if (mResId == 0) {
- return;
- }
- show(mResId);
- }
-
- protected void onNextClick() {
- }
- }
-
}