Initial import of Theme Verification Test.
Most of what is left is writing more individual tests.
The framework itself is pretty much there at this point.
Change-Id: I838d90529212e6a1741dc5dc70f0d6ea505e637a
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 0a9c79e..ecf595a 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -59,6 +59,7 @@
CtsTelephonyTestCases \
CtsTestStubs \
CtsTextTestCases \
+ CtsThemeTestCases \
CtsUtilTestCases \
CtsViewTestCases \
CtsWebkitTestCases \
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 2d95899..c7e39dd 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -960,6 +960,25 @@
</intent-filter>
</service>
+ <activity android:name="android.theme.cts.ThemeTestRunnerActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ <activity android:name="android.theme.cts.ThemeTestGeneratorActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ <activity android:name="android.theme.cts.HomeActivity"
+ android:theme="@android:style/Theme.Holo">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
</application>
<!--Test for PackageManager, please put this at the very beginning-->
diff --git a/tests/res/drawable-hdpi/holo_button.png b/tests/res/drawable-hdpi/holo_button.png
new file mode 100644
index 0000000..6c99b45
--- /dev/null
+++ b/tests/res/drawable-hdpi/holo_button.png
Binary files differ
diff --git a/tests/res/drawable-hdpi/holo_button_pressed.png b/tests/res/drawable-hdpi/holo_button_pressed.png
new file mode 100644
index 0000000..e85707d
--- /dev/null
+++ b/tests/res/drawable-hdpi/holo_button_pressed.png
Binary files differ
diff --git a/tests/res/drawable-hdpi/holo_light_button.png b/tests/res/drawable-hdpi/holo_light_button.png
new file mode 100644
index 0000000..97ca453
--- /dev/null
+++ b/tests/res/drawable-hdpi/holo_light_button.png
Binary files differ
diff --git a/tests/res/drawable-hdpi/holo_light_button_pressed.png b/tests/res/drawable-hdpi/holo_light_button_pressed.png
new file mode 100644
index 0000000..f8ebec2
--- /dev/null
+++ b/tests/res/drawable-hdpi/holo_light_button_pressed.png
Binary files differ
diff --git a/tests/res/layout/button.xml b/tests/res/layout/button.xml
new file mode 100644
index 0000000..ea0aec9
--- /dev/null
+++ b/tests/res/layout/button.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+ <Button xmlns:android="http://schemas.android.com/apk/res/android"
+ android:text="@string/button"
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </Button>
diff --git a/tests/res/layout/home_activity.xml b/tests/res/layout/home_activity.xml
new file mode 100644
index 0000000..49174da
--- /dev/null
+++ b/tests/res/layout/home_activity.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <Button android:text="@string/holo_test"
+ android:id="@+id/button_holo"
+ android:onClick="onHoloTestClick"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </Button>
+ <Button android:text="@string/holo_generator"
+ android:id="@+id/button2"
+ android:onClick="onHoloGenClick"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </Button>
+ <Button android:text="@string/holo_light_test"
+ android:id="@+id/button3"
+ android:onClick="onHoloLightTestClick"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </Button>
+ <Button android:text="@string/holo_light_generator"
+ android:id="@+id/button4"
+ android:onClick="onHoloLightGenClick"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </Button>
+</LinearLayout>
diff --git a/tests/res/layout/testing_activity.xml b/tests/res/layout/testing_activity.xml
new file mode 100644
index 0000000..8b9a47a
--- /dev/null
+++ b/tests/res/layout/testing_activity.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </TextView>
+ <TextView android:id="@+id/text_reference"
+ android:text="@string/reference_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/text">
+ </TextView>
+ <ImageView android:id="@+id/reference_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/text_reference"
+ android:layout_below="@+id/text"/>
+ <TextView android:id="@+id/text_generated"
+ android:text="@string/generated_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toLeftOf="@+id/generated_image"
+ android:layout_alignTop="@+id/generated_image">
+ </TextView>
+ <ImageView android:id="@+id/generated_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/reference_image"
+ android:layout_alignLeft="@+id/reference_image"/>
+ <android.theme.cts.TesterViewGroup android:id="@+id/test_group"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/generated_image"/>
+</RelativeLayout>
diff --git a/tests/res/values/dimens.xml b/tests/res/values/dimens.xml
index 2a8f76e..f0c57c2 100755
--- a/tests/res/values/dimens.xml
+++ b/tests/res/values/dimens.xml
@@ -38,6 +38,9 @@
<item name="frac25510pperc" type="dimen" format="fraction">25510%p</item>
<item name="frac25610pperc" type="dimen" format="fraction">25610%p</item>
<item name="frac6553510pperc" type="dimen" format="fraction">6553510%p</item>
- <item name="frac6553610pperc" type="dimen" format="fraction">6553610%p</item>
+ <item name="frac6553610pperc" type="dimen" format="fraction">6553610%p</item>
+
+ <dimen name="reference_width">320dp</dimen>
+ <dimen name="reference_height">480dp</dimen>
</resources>
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
index 8fcd75a..27ef32f 100644
--- a/tests/res/values/strings.xml
+++ b/tests/res/values/strings.xml
@@ -151,4 +151,13 @@
<string name="version_v3">base</string>
<string name="authenticator_label">Android CTS</string>
<string name="search_label">Android CTS</string>
+
+
+ <string name="button">Button</string>
+ <string name="holo_test">Holo Test</string>
+ <string name="holo_generator">Holo Generator</string>
+ <string name="holo_light_test">Holo Light Test</string>
+ <string name="holo_light_generator">Holo Light Generator</string>
+ <string name="reference_image">Reference Image: </string>
+ <string name="generated_image">Generated Image: </string>
</resources>
diff --git a/tests/src/android/theme/cts/HomeActivity.java b/tests/src/android/theme/cts/HomeActivity.java
new file mode 100644
index 0000000..04b75a1
--- /dev/null
+++ b/tests/src/android/theme/cts/HomeActivity.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import com.android.cts.stub.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+/**
+ * This activity exists solely for debugging purposes.
+ */
+public class HomeActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.home_activity);
+ }
+
+ public void onHoloTestClick(View view) {
+ Intent intent = new Intent(this, ThemeTestRunnerActivity.class);
+ intent.putExtra(ThemeTests.EXTRA_THEME_ID, android.R.style.Theme_Holo);
+ intent.putExtra(ThemeTests.EXTRA_THEME_NAME, "holo");
+ intent.putExtra(ThemeTests.EXTRA_RUN_TESTS, true);
+ startActivity(intent);
+ }
+
+ public void onHoloGenClick(View view) {
+ Intent intent = new Intent(this, ThemeTestGeneratorActivity.class);
+ intent.putExtra(ThemeTests.EXTRA_THEME_ID, android.R.style.Theme_Holo);
+ intent.putExtra(ThemeTests.EXTRA_THEME_NAME, "holo");
+ startActivity(intent);
+ }
+
+ public void onHoloLightTestClick(View view) {
+ Intent intent = new Intent(this, ThemeTestRunnerActivity.class);
+ intent.putExtra(ThemeTests.EXTRA_THEME_ID, android.R.style.Theme_Holo_Light);
+ intent.putExtra(ThemeTests.EXTRA_THEME_NAME, "holo_light");
+ intent.putExtra(ThemeTests.EXTRA_RUN_TESTS, true);
+ startActivity(intent);
+ }
+
+ public void onHoloLightGenClick(View view) {
+ Intent intent = new Intent(this, ThemeTestGeneratorActivity.class);
+ intent.putExtra(ThemeTests.EXTRA_THEME_ID, android.R.style.Theme_Holo_Light);
+ intent.putExtra(ThemeTests.EXTRA_THEME_NAME, "holo_light");
+ startActivity(intent);
+ }
+}
diff --git a/tests/src/android/theme/cts/TesterViewGroup.java b/tests/src/android/theme/cts/TesterViewGroup.java
new file mode 100644
index 0000000..f8f9b8f
--- /dev/null
+++ b/tests/src/android/theme/cts/TesterViewGroup.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import com.android.cts.stub.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Custom view group to handle density changes while maintaining screen independence.
+ */
+public class TesterViewGroup extends ViewGroup {
+ private int mReferenceWidthDp;
+ private int mReferenceHeightDp;
+
+ public TesterViewGroup(Context context) {
+ this(context, null);
+ }
+
+ public TesterViewGroup(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ Resources resources = context.getResources();
+
+ mReferenceWidthDp = resources.getDimensionPixelSize(R.dimen.reference_width);
+ mReferenceHeightDp = resources.getDimensionPixelSize(R.dimen.reference_height);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ if (!changed) {
+ return;
+ }
+
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ widthMeasureSpec = getMeasureSpec(LayoutParams.MATCH_PARENT, mReferenceWidthDp);
+ heightMeasureSpec = getMeasureSpec(LayoutParams.MATCH_PARENT, mReferenceHeightDp);
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+
+ LayoutParams params = child.getLayoutParams();
+
+ int height = getMeasureSpec(params.height, mReferenceWidthDp);
+ int width = getMeasureSpec(params.width, mReferenceHeightDp);
+ child.measure(width, height);
+ }
+ }
+
+ private int getMeasureSpec(int val, int referenceSize) {
+ if (val == LayoutParams.MATCH_PARENT || val == LayoutParams.FILL_PARENT) {
+ return MeasureSpec.makeMeasureSpec(referenceSize, MeasureSpec.EXACTLY);
+ } else if (val == LayoutParams.WRAP_CONTENT) {
+ return MeasureSpec.makeMeasureSpec(referenceSize, MeasureSpec.AT_MOST);
+ } else {
+ return val;
+ }
+ }
+}
diff --git a/tests/src/android/theme/cts/ThemeTestGeneratorActivity.java b/tests/src/android/theme/cts/ThemeTestGeneratorActivity.java
new file mode 100644
index 0000000..37c8091
--- /dev/null
+++ b/tests/src/android/theme/cts/ThemeTestGeneratorActivity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import com.android.cts.stub.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import junit.framework.Assert;
+
+public class ThemeTestGeneratorActivity extends Activity {
+
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ int themeId = intent.getIntExtra(ThemeTests.EXTRA_THEME_ID, 0);
+
+ // test should fail if no theme is set
+ Assert.assertTrue("No Theme Resource ID set", themeId != 0);
+
+ String themeName = intent.getStringExtra(ThemeTests.EXTRA_THEME_NAME);
+
+ setTheme(themeId);
+ setContentView(R.layout.testing_activity);
+
+ ThemeTester tester = new ThemeTester(this, themeName);
+ tester.generateTests();
+ }
+}
diff --git a/tests/src/android/theme/cts/ThemeTestInfo.java b/tests/src/android/theme/cts/ThemeTestInfo.java
new file mode 100644
index 0000000..c629f43
--- /dev/null
+++ b/tests/src/android/theme/cts/ThemeTestInfo.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+/**
+ * Class that represents a test case. Add a new one to the list of tests in ThemeTests.java
+ * in order to create a new test.
+ */
+public class ThemeTestInfo {
+ private int mResourceId;
+ private ThemeTestModifier mModifier;
+ private String mFilename;
+
+ /**
+ * Creates a new theme test.
+ * @param layoutResourceId The resource ID of the layout to use for this test.
+ * @param modifier The {@link ThemeTestModifier} to use in order to modify the layout
+ * of the test.
+ * @param testname The UNIQUE name of the test.
+ */
+ public ThemeTestInfo(int layoutResourceId, ThemeTestModifier modifier, String testname) {
+ mResourceId = layoutResourceId;
+ mModifier = modifier;
+ mFilename = testname;
+ }
+
+ public int getLayoutResourceId() {
+ return mResourceId;
+ }
+
+ public ThemeTestModifier getThemeModifier() {
+ return mModifier;
+ }
+
+ public String getTestName() {
+ return mFilename;
+ }
+}
diff --git a/tests/src/android/theme/cts/ThemeTestModifier.java b/tests/src/android/theme/cts/ThemeTestModifier.java
new file mode 100644
index 0000000..436b2e2
--- /dev/null
+++ b/tests/src/android/theme/cts/ThemeTestModifier.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import android.view.View;
+
+/**
+ * Interface that should be implemented if you want to modify the view being tested.
+ *
+ * For a sample implementation, see {@link ViewPressedModifier}.
+ */
+public interface ThemeTestModifier {
+ /**
+ * Define this function in order to modify the layout for your test.
+ * The View that is passed in is the root of layout that is specified in the test.
+ * @param view The root view of the layout.
+ */
+ public void modifyView(View view);
+}
diff --git a/tests/src/android/theme/cts/ThemeTestRunnerActivity.java b/tests/src/android/theme/cts/ThemeTestRunnerActivity.java
new file mode 100644
index 0000000..631c5bc
--- /dev/null
+++ b/tests/src/android/theme/cts/ThemeTestRunnerActivity.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import com.android.cts.stub.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import junit.framework.Assert;
+
+public class ThemeTestRunnerActivity extends Activity {
+ private ThemeTester mTester;
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ int themeId = intent.getIntExtra(ThemeTests.EXTRA_THEME_ID, 0);
+
+ // test should fail if no theme is set
+ Assert.assertTrue("No Theme Resource ID set", themeId != 0);
+
+ String themeName = intent.getStringExtra(ThemeTests.EXTRA_THEME_NAME);
+
+ setTheme(themeId);
+ setContentView(R.layout.testing_activity);
+
+ mTester = new ThemeTester(this, themeName);
+
+ if (intent.getBooleanExtra(ThemeTests.EXTRA_RUN_TESTS, false)) {
+ mTester.runTests();
+ }
+ }
+
+ /**
+ * Runs the theme tests for the theme that was created.
+ */
+ public void runTests() {
+ mTester.runTests();
+ }
+}
diff --git a/tests/src/android/theme/cts/ThemeTester.java b/tests/src/android/theme/cts/ThemeTester.java
new file mode 100644
index 0000000..c6be2d7
--- /dev/null
+++ b/tests/src/android/theme/cts/ThemeTester.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import com.android.cts.stub.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import junit.framework.Assert;
+
+/**
+ * This class runs the series of tests for a specific theme in the activity.
+ *
+ * <p>
+ * Additionally, this class can also generate the good versions of bitmaps to use for testing.
+ */
+public class ThemeTester {
+ private Activity mActivity;
+ private String mThemeName;
+ private ImageView mReferenceImage;
+ private ImageView mGeneratedImage;
+ private TextView mText;
+ private TesterViewGroup mRoot;
+
+ /**
+ * Creates a ThemeTester to run all of the tests.
+ * @param activity Activity that serves as a test harness for this theme test.
+ * @param themeName Name of the theme being tested.
+ */
+ public ThemeTester(Activity activity, String themeName) {
+ mActivity = activity;
+ mThemeName = themeName;
+ mRoot = (TesterViewGroup) mActivity.findViewById(R.id.test_group);
+
+ // TODO - remove views that exist for debugging only
+ mReferenceImage = (ImageView) mActivity.findViewById(R.id.reference_image);
+ mGeneratedImage = (ImageView) mActivity.findViewById(R.id.generated_image);
+ mText = (TextView) mActivity.findViewById(R.id.text);
+ }
+
+ /**
+ * Run all of the tests.
+ */
+ public void runTests() {
+ ThemeTestInfo[] tests = ThemeTests.getTests();
+ for (final ThemeTestInfo test : tests) {
+ mText.post(new Runnable() {
+ public void run() {
+ testViewFromId(test);
+ }
+ });
+ }
+ }
+
+ /**
+ * Generate all of the tests, saving them to Bitmaps in the application's data folder.
+ */
+ public void generateTests() {
+ ThemeTestInfo[] tests = ThemeTests.getTests();
+ for (final ThemeTestInfo test : tests) {
+ mText.post(new Runnable() {
+ public void run() {
+ mText.setText("Bitmaps saved");
+ generateViewFromId(test);
+ }
+ });
+ }
+ }
+
+ private void testViewFromId(ThemeTestInfo test) {
+ processBitmapFromViewId(test.getLayoutResourceId(), test.getThemeModifier(),
+ new BitmapComparer(mThemeName + "_" + test.getTestName()));
+ }
+
+ private void generateViewFromId(ThemeTestInfo test) {
+ processBitmapFromViewId(test.getLayoutResourceId(), test.getThemeModifier(),
+ new BitmapGenerator(mThemeName + "_" + test.getTestName()));
+ }
+
+ private void processBitmapFromViewId(
+ int resid, ThemeTestModifier modifier, final BitmapProcessor processor) {
+ final View view = constructViewFromLayoutId(resid, modifier);
+
+ view.post(new Runnable() {
+ public void run() {
+ Bitmap bitmap = Bitmap.createBitmap(
+ view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
+
+ Canvas canvas = new Canvas(bitmap);
+ view.draw(canvas);
+ mGeneratedImage.setImageBitmap(bitmap);
+
+ if (processor.processBitmap(bitmap)) {
+ mText.setText(mText.getText() + "\nBitmaps identical");
+ } else {
+ mText.setText(mText.getText() + "\nBitmaps differ");
+ }
+
+ mRoot.removeView(view);
+ }
+ });
+ }
+
+ /**
+ * Inflates and returns the view and performs and modifications of it as required by the test.
+ * @param resid The resource id of the layout that will be constructed.
+ * @param modifier The ThemeTestModifier to modify the layout being tested.
+ * @return The root view of the layout being tested.
+ */
+ private View constructViewFromLayoutId(int resid, ThemeTestModifier modifier) {
+ LayoutInflater inflater = LayoutInflater.from(mActivity);
+
+ View view = inflater.inflate(resid, mRoot, false);
+ mRoot.addView(view);
+
+ mRoot.measure(0, 0); // don't care about the first two values - we build our reference size
+ mRoot.layout(0, 0, mRoot.getMeasuredWidth(), mRoot.getMeasuredHeight());
+
+ if (modifier != null) {
+ modifier.modifyView(view);
+ }
+
+ return view;
+ }
+
+ /**
+ * Simple interface in order to share code between the bitmap comparison and bitmap generation
+ * steps.
+ */
+ private interface BitmapProcessor {
+ public boolean processBitmap(Bitmap bitmap);
+ }
+
+ /**
+ * Implementation of {@link BitmapProcessor} that compares the created bitmap
+ * to a known good version. Asserts if the bitmaps do not compare.
+ */
+ private class BitmapComparer implements BitmapProcessor {
+ String mBitmapIdName;
+
+ public BitmapComparer(String filename) {
+ mBitmapIdName = filename;
+ }
+
+ @Override
+ public boolean processBitmap(Bitmap bitmap) {
+ Resources r = mActivity.getResources();
+ int resourceId = r.getIdentifier(mBitmapIdName, "drawable", mActivity.getPackageName());
+
+ BitmapDrawable drawable = (BitmapDrawable) r.getDrawable(resourceId);
+ Bitmap bmp2 = drawable.getBitmap();
+ mReferenceImage.setImageBitmap(bmp2);
+
+ Assert.assertTrue("Test failed: " + mBitmapIdName, bmp2.sameAs(bitmap));
+
+ return true;
+ }
+ }
+
+ /**
+ * Implementation of {@link BitmapProcessor} that creates a known-good version of the
+ * bitmap and saves it to the applications data folder.
+ */
+ private class BitmapGenerator implements BitmapProcessor {
+ String mFilename;
+
+ public BitmapGenerator(String filename) {
+ mFilename = filename + ".png";
+ }
+
+ @Override
+ public boolean processBitmap(Bitmap bitmap) {
+ try {
+ FileOutputStream fos = mActivity.openFileOutput(mFilename, Context.MODE_PRIVATE);
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
+ fos.close();
+ } catch (FileNotFoundException e) {
+ // TODO - break loudly
+ } catch (IOException e) {
+ // TODO - break loudly
+ }
+
+ return false;
+ }
+
+ }
+}
diff --git a/tests/src/android/theme/cts/ThemeTests.java b/tests/src/android/theme/cts/ThemeTests.java
new file mode 100644
index 0000000..19db730
--- /dev/null
+++ b/tests/src/android/theme/cts/ThemeTests.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import com.android.cts.stub.R;
+
+public class ThemeTests {
+ /**
+ * Theme name to test.
+ */
+ public static final String EXTRA_THEME_NAME = "android.intent.extra.THEME_NAME";
+
+ /**
+ * Theme ID to test.
+ */
+ public static final String EXTRA_THEME_ID = "android.intent.extra.THEME_ID";
+
+ /**
+ * Use solely for debugging. The actual intent that runs the tests will not have this flag.
+ */
+ public static final String EXTRA_RUN_TESTS = "android.intent.extra.RUN_TESTS";
+
+ /**
+ * The list of tests to run for each theme.<p>
+ *
+ * In order to create a new test, follow these steps.<p>
+ * 1. Create a layout file for the test you wish to run.<p>
+ * 2. (Optional) Create a class that derives from ThemeTestModifier
+ * that will modify the root view of your created layout. Set to null if you do not want
+ * to modify the view from the layout version.<p>
+ * 3. Create a unique String for the name of the test.<p>
+ * 4. Add all of the above to the list of tests. as a new {@link ThemeTestInfo}.
+ */
+ private static final ThemeTestInfo[] TESTS = new ThemeTestInfo[] {
+ new ThemeTestInfo(R.layout.button, null, "button"),
+ new ThemeTestInfo(R.layout.button, new ViewPressedModifier(), "button_pressed")};
+
+ /**
+ * Returns the list of tests to run on a particular theme.
+ *
+ * In order to create a new test, follow these steps.<p>
+ * 1. Create a layout file for the test you wish to run.<p>
+ * 2. (Optional) Create a class that derives from ThemeTestModifier
+ * that will modify the root view of your created layout. Set to null if you do not want
+ * to modify the view from the layout version.<p>
+ * 3. Create a unique String for the name of the test.<p>
+ * 4. Add all of the above to the list of tests. as a new {@link ThemeTestInfo}.
+ * @return The list of tests.
+ */
+ public static ThemeTestInfo[] getTests() {
+ return TESTS;
+ }
+}
diff --git a/tests/src/android/theme/cts/ViewPressedModifier.java b/tests/src/android/theme/cts/ViewPressedModifier.java
new file mode 100644
index 0000000..8a97c7f
--- /dev/null
+++ b/tests/src/android/theme/cts/ViewPressedModifier.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import android.view.View;
+
+/**
+ * Modifies the root view of a test so that it is in the pressed state.
+ */
+public class ViewPressedModifier implements ThemeTestModifier {
+
+ @Override
+ public void modifyView(View view) {
+ view.setPressed(true);
+ }
+
+}
diff --git a/tests/tests/theme/Android.mk b/tests/tests/theme/Android.mk
new file mode 100644
index 0000000..b28e6b3
--- /dev/null
+++ b/tests/tests/theme/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2011 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsThemeTestCases
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
+
+include $(BUILD_PACKAGE)
diff --git a/tests/tests/theme/AndroidManifest.xml b/tests/tests/theme/AndroidManifest.xml
new file mode 100644
index 0000000..55afc7d
--- /dev/null
+++ b/tests/tests/theme/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.theme">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+ android:targetPackage="com.android.cts.stub"
+ android:label="CTS tests for themes">
+ </instrumentation>
+
+</manifest>
diff --git a/tests/tests/theme/src/android/theme/cts/ThemeTest.java b/tests/tests/theme/src/android/theme/cts/ThemeTest.java
new file mode 100644
index 0000000..df00d7b
--- /dev/null
+++ b/tests/tests/theme/src/android/theme/cts/ThemeTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 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 android.theme.cts;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link #testActivityTestCaseSetUpProperly}.
+ */
+public class ThemeTest extends ActivityInstrumentationTestCase2<ThemeTestRunnerActivity> {
+ private Instrumentation mInstrumentation;
+
+ /**
+ * Creates an {@link ActivityInstrumentationTestCase2}
+ * for the {@link ThemeTestRunnerActivity} activity.
+ */
+ public ThemeTest() {
+ super(ThemeTestRunnerActivity.class);
+
+ mInstrumentation = getInstrumentation();
+ }
+
+ public void testHoloTheme() {
+ runThemeTest(android.R.style.Theme_Holo, "holo");
+ }
+
+ public void testHoloLightTheme() {
+ runThemeTest(android.R.style.Theme_Holo_Light, "holo_light");
+ }
+
+ /**
+ * Runs the theme test given the appropriate theme resource id and theme name.
+ * @param resourceId Resource ID of the theme being tested.
+ * @param themeName Name of the theme being tested, e.g., "holo", "holo_light", etc
+ */
+ private void runThemeTest(int resourceId, String themeName) {
+ if (mInstrumentation == null) {
+ mInstrumentation = getInstrumentation();
+ }
+
+ Intent intent = new Intent();
+ intent.putExtra(ThemeTests.EXTRA_THEME_ID, resourceId);
+ intent.putExtra(ThemeTests.EXTRA_THEME_NAME, themeName);
+ setActivityIntent(intent);
+
+ final ThemeTestRunnerActivity activity = getActivity();
+
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+ activity.runTests();
+ }
+ });
+
+ mInstrumentation.waitForIdleSync();
+ }
+}