diff options
author | Kevin Neas <kneas@google.com> | 2015-11-12 12:17:26 -0800 |
---|---|---|
committer | Kevin Neas <kneas@google.com> | 2015-11-13 01:09:58 +0000 |
commit | 0972c262430b42d573cc9cde8d16d273991a98a9 (patch) | |
tree | 826ae36fd298067a1f278b9f3276ebe6ee02e05b /tests | |
parent | 4f822bbf2a1c44c9dc5668857aa8cf7f0e5969cc (diff) | |
download | frameworks_base-0972c262430b42d573cc9cde8d16d273991a98a9.zip frameworks_base-0972c262430b42d573cc9cde8d16d273991a98a9.tar.gz frameworks_base-0972c262430b42d573cc9cde8d16d273991a98a9.tar.bz2 |
DO NOT MERGE. Cherrypick UiBench from Master
UiBench apk for Jank tests for Emerald
Change-Id: Ib58a2b8ff76b18b9c41cbd513c8a16571b7a37a0
Diffstat (limited to 'tests')
44 files changed, 2356 insertions, 0 deletions
diff --git a/tests/UiBench/.gitignore b/tests/UiBench/.gitignore new file mode 100644 index 0000000..c39eac2 --- /dev/null +++ b/tests/UiBench/.gitignore @@ -0,0 +1,5 @@ +.gradle +.idea +*.iml +build +local.properties diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk new file mode 100644 index 0000000..0e678cd --- /dev/null +++ b/tests/UiBench/Android.mk @@ -0,0 +1,31 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +# omit gradle 'build' dir +LOCAL_SRC_FILES := $(call all-java-files-under,src) + +# use appcompat/support lib from the tree, so improvements/ +# regressions are reflected in test data +LOCAL_RESOURCE_DIR := \ + $(LOCAL_PATH)/res \ + frameworks/support/v7/appcompat/res \ + frameworks/support/v7/cardview/res \ + frameworks/support/v7/recyclerview/res + +LOCAL_AAPT_FLAGS := \ + --auto-add-overlay \ + --extra-packages android.support.v7.appcompat \ + --extra-packages android.support.v7.cardview \ + --extra-packages android.support.v7.recyclerview + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-v4 \ + android-support-v7-appcompat \ + android-support-v7-cardview \ + android-support-v7-recyclerview + +LOCAL_PACKAGE_NAME := UiBench + +include $(BUILD_PACKAGE) diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml new file mode 100644 index 0000000..7b4f01c --- /dev/null +++ b/tests/UiBench/AndroidManifest.xml @@ -0,0 +1,165 @@ +<!-- + ~ Copyright (C) 2015 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" + xmlns:tools="http://schemas.android.com/tools" + package="com.android.test.uibench"> + + <application + android:allowBackup="false" + android:theme="@style/Theme.AppCompat.Light.DarkActionBar" + tools:ignore="MissingApplicationIcon"> + <uses-library android:name="android.test.runner" /> + + <!-- Root navigation activity --> + <activity + android:name=".MainActivity" + android:label="UiBench"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <!-- General --> + <activity + android:name=".DialogListActivity" + android:label="General/Dialog List" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".GlTextureViewActivity" + android:label="General/GL TextureView" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".FullscreenOverdrawActivity" + android:label="General/Fullscreen Overdraw" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".InvalidateActivity" + android:label="General/Invalidate" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".TrivialAnimationActivity" + android:label="General/Trivial Animation" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".TrivialListActivity" + android:label="General/Trivial ListView" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".TrivialRecyclerViewActivity" + android:label="General/Trivial Recycler ListView" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".ActivityTransition" + android:label="Transitions/Activity Transition" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".ActivityTransitionDetails" + android:label="Transitions/Activity Transition " > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <!-- Part of ActivityTransition test above, so not in TEST category --> + </intent-filter> + </activity> + + <!-- Rendering --> + <activity + android:name=".BitmapUploadActivity" + android:label="Rendering/Bitmap Upload" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".ShadowGridActivity" + android:label="Rendering/Shadow Grid" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + + <!-- Inflation --> + <activity + android:name=".InflatingListActivity" + android:label="Inflation/Inflating ListView" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + + <!-- Text --> + <activity + android:name=".EditTextTypeActivity" + android:label="Text/EditText Typing" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".TextCacheLowHitrateActivity" + android:label="Text/Layout Cache Low Hitrate" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + <activity + android:name=".TextCacheHighHitrateActivity" + android:label="Text/Layout Cache High Hitrate" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.uibench.TEST" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/tests/UiBench/build.gradle b/tests/UiBench/build.gradle new file mode 100644 index 0000000..0756a8a --- /dev/null +++ b/tests/UiBench/build.gradle @@ -0,0 +1,39 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.3.0' + + } +} + +apply plugin: 'com.android.application' + +android { + compileSdkVersion 23 + buildToolsVersion "22.0.0" + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" + } + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + res.srcDirs = ['res'] + } + } +} + +dependencies { + // Dependencies enumerated specifically for platform-independent / reproducible builds. + compile 'com.android.support:support-v4:23.0.1' + compile 'com.android.support:appcompat-v7:23.0.1' + compile 'com.android.support:cardview-v7:23.0.1' + compile 'com.android.support:recyclerview-v7:23.0.1' +} diff --git a/tests/UiBench/gradle/wrapper/gradle-wrapper.jar b/tests/UiBench/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 0000000..8c0fb64 --- /dev/null +++ b/tests/UiBench/gradle/wrapper/gradle-wrapper.jar diff --git a/tests/UiBench/gradle/wrapper/gradle-wrapper.properties b/tests/UiBench/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..12582f8 --- /dev/null +++ b/tests/UiBench/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Aug 26 10:51:13 PDT 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip diff --git a/tests/UiBench/res/drawable-nodpi/ball.jpg b/tests/UiBench/res/drawable-nodpi/ball.jpg Binary files differnew file mode 100644 index 0000000..2960b73 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/ball.jpg diff --git a/tests/UiBench/res/drawable-nodpi/block.jpg b/tests/UiBench/res/drawable-nodpi/block.jpg Binary files differnew file mode 100644 index 0000000..04c22a0 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/block.jpg diff --git a/tests/UiBench/res/drawable-nodpi/ducky.jpg b/tests/UiBench/res/drawable-nodpi/ducky.jpg Binary files differnew file mode 100644 index 0000000..830bbe3 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/ducky.jpg diff --git a/tests/UiBench/res/drawable-nodpi/frantic.jpg b/tests/UiBench/res/drawable-nodpi/frantic.jpg Binary files differnew file mode 100644 index 0000000..4c62333 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/frantic.jpg diff --git a/tests/UiBench/res/drawable-nodpi/jellies.jpg b/tests/UiBench/res/drawable-nodpi/jellies.jpg Binary files differnew file mode 100644 index 0000000..ee2b5c6 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/jellies.jpg diff --git a/tests/UiBench/res/drawable-nodpi/large_photo.jpg b/tests/UiBench/res/drawable-nodpi/large_photo.jpg Binary files differnew file mode 100644 index 0000000..e23dbb0 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/large_photo.jpg diff --git a/tests/UiBench/res/drawable-nodpi/mug.jpg b/tests/UiBench/res/drawable-nodpi/mug.jpg Binary files differnew file mode 100644 index 0000000..e149e19 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/mug.jpg diff --git a/tests/UiBench/res/drawable-nodpi/pencil.jpg b/tests/UiBench/res/drawable-nodpi/pencil.jpg Binary files differnew file mode 100644 index 0000000..e348311 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/pencil.jpg diff --git a/tests/UiBench/res/drawable-nodpi/scissors.jpg b/tests/UiBench/res/drawable-nodpi/scissors.jpg Binary files differnew file mode 100644 index 0000000..caf0ce8 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/scissors.jpg diff --git a/tests/UiBench/res/drawable-nodpi/woot.jpg b/tests/UiBench/res/drawable-nodpi/woot.jpg Binary files differnew file mode 100644 index 0000000..ccaef67 --- /dev/null +++ b/tests/UiBench/res/drawable-nodpi/woot.jpg diff --git a/tests/UiBench/res/layout/activity_bitmap_upload.xml b/tests/UiBench/res/layout/activity_bitmap_upload.xml new file mode 100644 index 0000000..70faa07 --- /dev/null +++ b/tests/UiBench/res/layout/activity_bitmap_upload.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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:id="@+id/upload_root" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="10dp" + android:clipToPadding="false"> + <android.support.v7.widget.CardView + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1"> + <view class="com.android.test.uibench.BitmapUploadActivity$UploadView" + android:id="@+id/upload_view" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + </android.support.v7.widget.CardView> + + <android.support.v4.widget.Space + android:layout_height="10dp" + android:layout_width="match_parent" /> + + <android.support.v7.widget.CardView + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <android.support.v4.widget.Space + android:layout_height="10dp" + android:layout_width="match_parent" /> + + <android.support.v7.widget.CardView + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> +</LinearLayout>
\ No newline at end of file diff --git a/tests/UiBench/res/layout/activity_invalidate.xml b/tests/UiBench/res/layout/activity_invalidate.xml new file mode 100644 index 0000000..34bcca9 --- /dev/null +++ b/tests/UiBench/res/layout/activity_invalidate.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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:id="@+id/invalidate_root" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> + <include layout="@layout/invalidate_row"/> +</LinearLayout>
\ No newline at end of file diff --git a/tests/UiBench/res/layout/activity_transition.xml b/tests/UiBench/res/layout/activity_transition.xml new file mode 100644 index 0000000..d4c6610 --- /dev/null +++ b/tests/UiBench/res/layout/activity_transition.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> +<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clipChildren="true" + android:columnCount="2" + android:rowCount="4"> + <ImageView + android:id="@+id/ducky" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:scaleType="centerCrop" + android:layout_column="0" + android:layout_row="0" + android:src="@drawable/ducky" + android:onClick="clicked" + android:transitionName="ducky"/> + <ImageView + android:id="@+id/woot" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/woot" + android:layout_column="1" + android:layout_row="0" + android:onClick="clicked" + android:transitionName="woot"/> + <ImageView + android:id="@+id/ball" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/ball" + android:layout_column="0" + android:layout_row="1" + android:onClick="clicked" + android:transitionName="ball"/> + <ImageView + android:id="@+id/block" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/block" + android:layout_column="1" + android:layout_row="1" + android:onClick="clicked" + android:transitionName="block"/> + <ImageView + android:id="@+id/jellies" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/jellies" + android:layout_column="0" + android:layout_row="2" + android:onClick="clicked" + android:transitionName="jellies"/> + <ImageView + android:id="@+id/mug" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/mug" + android:layout_column="1" + android:layout_row="2" + android:onClick="clicked" + android:transitionName="mug"/> + <ImageView + android:id="@+id/pencil" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/pencil" + android:layout_column="0" + android:layout_row="3" + android:onClick="clicked" + android:transitionName="pencil"/> + <ImageView + android:id="@+id/scissors" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/scissors" + android:layout_column="1" + android:layout_row="3" + android:onClick="clicked" + android:transitionName="scissors"/> +</GridLayout>
\ No newline at end of file diff --git a/tests/UiBench/res/layout/activity_transition_details.xml b/tests/UiBench/res/layout/activity_transition_details.xml new file mode 100644 index 0000000..1022d2f --- /dev/null +++ b/tests/UiBench/res/layout/activity_transition_details.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + <ImageView + android:id="@+id/titleImage" + android:layout_height="0px" + android:layout_weight="1" + android:layout_width="match_parent" + android:scaleType="centerCrop" + android:transitionName="hero" + android:onClick="clicked"/> + <View + android:layout_width="match_parent" + android:layout_height="2dp" + android:background="#808080"/> + <TextView + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="Sample Picture" + android:textSize="30sp" + android:textColor="#FFF"/> +</LinearLayout>
\ No newline at end of file diff --git a/tests/UiBench/res/layout/card_row.xml b/tests/UiBench/res/layout/card_row.xml new file mode 100644 index 0000000..215f9df --- /dev/null +++ b/tests/UiBench/res/layout/card_row.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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="horizontal" + android:layout_width="match_parent" + android:layout_height="100dp" + android:paddingStart="10dp" + android:paddingEnd="10dp" + android:paddingTop="5dp" + android:paddingBottom="5dp" + android:clipToPadding="false" + android:background="@null"> + <android.support.v7.widget.CardView + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1"> + <TextView + android:id="@+id/card_text" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + </android.support.v7.widget.CardView> + + <android.support.v4.widget.Space + android:layout_height="match_parent" + android:layout_width="10dp" /> + + <android.support.v7.widget.CardView + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" /> +</LinearLayout>
\ No newline at end of file diff --git a/tests/UiBench/res/layout/invalidate_row.xml b/tests/UiBench/res/layout/invalidate_row.xml new file mode 100644 index 0000000..9feefde --- /dev/null +++ b/tests/UiBench/res/layout/invalidate_row.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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="horizontal" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1"> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <view class="com.android.test.uibench.InvalidateActivity$ColorView" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> +</LinearLayout>
\ No newline at end of file diff --git a/tests/UiBench/res/layout/recycler_view.xml b/tests/UiBench/res/layout/recycler_view.xml new file mode 100644 index 0000000..54c5b58 --- /dev/null +++ b/tests/UiBench/res/layout/recycler_view.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> +<android.support.v7.widget.RecyclerView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/recyclerView" + android:layout_width="match_parent" + android:layout_height="match_parent"/> diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java new file mode 100644 index 0000000..1106a13 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.app.ActivityOptions; +import android.app.SharedElementCallback; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ImageView; + +import java.util.List; +import java.util.Map; + +public class ActivityTransition extends AppCompatActivity { + private static final String KEY_ID = "ViewTransitionValues:id"; + + private ImageView mHero; + + public static final int[] DRAWABLES = { + R.drawable.ball, + R.drawable.block, + R.drawable.ducky, + R.drawable.jellies, + R.drawable.mug, + R.drawable.pencil, + R.drawable.scissors, + R.drawable.woot, + }; + + public static final int[] IDS = { + R.id.ball, + R.id.block, + R.id.ducky, + R.id.jellies, + R.id.mug, + R.id.pencil, + R.id.scissors, + R.id.woot, + }; + + public static final String[] NAMES = { + "ball", + "block", + "ducky", + "jellies", + "mug", + "pencil", + "scissors", + "woot", + }; + + public static int getIdForKey(String id) { + return IDS[getIndexForKey(id)]; + } + + public static int getDrawableIdForKey(String id) { + return DRAWABLES[getIndexForKey(id)]; + } + + public static int getIndexForKey(String id) { + for (int i = 0; i < NAMES.length; i++) { + String name = NAMES[i]; + if (name.equals(id)) { + return i; + } + } + return 2; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK)); + setContentView(R.layout.activity_transition); + setupHero(); + } + + private void setupHero() { + String name = getIntent().getStringExtra(KEY_ID); + mHero = null; + if (name != null) { + mHero = (ImageView) findViewById(getIdForKey(name)); + setEnterSharedElementCallback(new SharedElementCallback() { + @Override + public void onMapSharedElements(List<String> names, + Map<String, View> sharedElements) { + sharedElements.put("hero", mHero); + } + }); + } + } + + public void clicked(View v) { + mHero = (ImageView) v; + Intent intent = new Intent(this, ActivityTransitionDetails.class); + intent.putExtra(KEY_ID, v.getTransitionName()); + ActivityOptions activityOptions + = ActivityOptions.makeSceneTransitionAnimation(this, mHero, "hero"); + startActivity(intent, activityOptions.toBundle()); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java new file mode 100644 index 0000000..a654c61 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.app.ActivityOptions; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ImageView; + +import com.android.test.uibench.ActivityTransition; +import com.android.test.uibench.R; + + +public class ActivityTransitionDetails extends AppCompatActivity { + private static final String KEY_ID = "ViewTransitionValues:id"; + private int mImageResourceId = R.drawable.ducky; + private String mName = "ducky"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.DKGRAY)); + setContentView(R.layout.activity_transition_details); + ImageView titleImage = (ImageView) findViewById(R.id.titleImage); + titleImage.setImageDrawable(getHeroDrawable()); + } + + private Drawable getHeroDrawable() { + String name = getIntent().getStringExtra(KEY_ID); + if (name != null) { + mName = name; + mImageResourceId = ActivityTransition.getDrawableIdForKey(name); + } + + return getResources().getDrawable(mImageResourceId); + } + + public void clicked(View v) { + Intent intent = new Intent(this, ActivityTransition.class); + intent.putExtra(KEY_ID, mName); + ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation( + this, v, "hero"); + startActivity(intent, activityOptions.toBundle()); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java new file mode 100644 index 0000000..e2bf897 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Rect; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.View; + +public class BitmapUploadActivity extends AppCompatActivity { + public static class UploadView extends View { + private int mColorValue; + private Bitmap mBitmap; + private final DisplayMetrics mMetrics = new DisplayMetrics(); + private final Rect mRect = new Rect(); + + public UploadView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @SuppressWarnings("unused") + public void setColorValue(int colorValue) { + if (colorValue == mColorValue) return; + + mColorValue = colorValue; + + // modify the bitmap's color to ensure it's uploaded to the GPU + mBitmap.eraseColor(Color.rgb(mColorValue, 255 - mColorValue, 255)); + + invalidate(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + getDisplay().getMetrics(mMetrics); + int minDisplayDimen = Math.min(mMetrics.widthPixels, mMetrics.heightPixels); + int bitmapSize = Math.min((int) (minDisplayDimen * 0.75), 720); + if (mBitmap == null + || mBitmap.getWidth() != bitmapSize + || mBitmap.getHeight() != bitmapSize) { + mBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (mBitmap != null) { + mRect.set(0, 0, getWidth(), getHeight()); + canvas.drawBitmap(mBitmap, null, mRect, null); + } + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_bitmap_upload); + + // animate color to force bitmap uploads + UploadView uploadView = (UploadView) findViewById(R.id.upload_view); + ObjectAnimator colorValueAnimator = ObjectAnimator.ofInt(uploadView, "colorValue", 0, 255); + colorValueAnimator.setRepeatMode(ValueAnimator.REVERSE); + colorValueAnimator.setRepeatCount(ValueAnimator.INFINITE); + colorValueAnimator.start(); + + // animate scene root to guarantee there's a minimum amount of GPU rendering work + View uploadRoot = findViewById(R.id.upload_root); + ObjectAnimator yAnimator = ObjectAnimator.ofFloat(uploadRoot, "translationY", 0, 100); + yAnimator.setRepeatMode(ValueAnimator.REVERSE); + yAnimator.setRepeatCount(ValueAnimator.INFINITE); + yAnimator.start(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/DialogListActivity.java b/tests/UiBench/src/com/android/test/uibench/DialogListActivity.java new file mode 100644 index 0000000..fe712d5 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/DialogListActivity.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +public class DialogListActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ListView listView = new ListView(this); + listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + TextUtils.buildSimpleStringList())); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("Dialog"); + builder.setView(listView); + builder.create().show(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java b/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java new file mode 100644 index 0000000..08ab510 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.app.Instrumentation; +import android.os.Bundle; +import android.os.Looper; +import android.os.MessageQueue; +import android.support.v7.app.AppCompatActivity; +import android.view.KeyEvent; +import android.widget.EditText; + +import java.util.concurrent.Semaphore; + +/** + * Note: currently incomplete, complexity of input continuously grows, instead of looping + * over a stable amount of work. + * + * Simulates typing continuously into an EditText. + */ +public class EditTextTypeActivity extends AppCompatActivity { + Thread mThread; + + private static String sSeedText = ""; + static { + final int count = 100; + final String string = "hello "; + + StringBuilder builder = new StringBuilder(count * string.length()); + for (int i = 0; i < count; i++) { + builder.append(string); + } + sSeedText = builder.toString(); + } + + final Object mLock = new Object(); + boolean mShouldStop = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + EditText editText = new EditText(this); + editText.setText(sSeedText); + setContentView(editText); + + final Instrumentation instrumentation = new Instrumentation(); + final Semaphore sem = new Semaphore(0); + MessageQueue.IdleHandler handler = new MessageQueue.IdleHandler() { + @Override + public boolean queueIdle() { + // TODO: consider other signaling approaches + sem.release(); + return true; + } + }; + Looper.myQueue().addIdleHandler(handler); + synchronized (mLock) { + mShouldStop = false; + } + mThread = new Thread(new Runnable() { + int codes[] = { KeyEvent.KEYCODE_H, KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_L, + KeyEvent.KEYCODE_L, KeyEvent.KEYCODE_O, KeyEvent.KEYCODE_SPACE }; + int i = 0; + @Override + public void run() { + while (true) { + try { + sem.acquire(); + } catch (InterruptedException e) { + // TODO, maybe + } + int code = codes[i % codes.length]; + if (i % 100 == 99) code = KeyEvent.KEYCODE_ENTER; + + synchronized (mLock) { + if (mShouldStop) break; + } + + // TODO: bit of a race here, since the event can arrive after pause/stop. + // (Can't synchronize on key send, since it's synchronous.) + instrumentation.sendKeyDownUpSync(code); + i++; + } + } + }); + mThread.start(); + } + + @Override + protected void onPause() { + synchronized (mLock) { + mShouldStop = true; + } + super.onPause(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java new file mode 100644 index 0000000..f1ecc56 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +/** + * Draws hundreds of levels of overdraw over the content area. + * + * This should all be optimized out by the renderer. + */ +public class FullscreenOverdrawActivity extends AppCompatActivity { + private class OverdrawView extends View { + Paint paint = new Paint(); + int mColorValue = 0; + + public OverdrawView(Context context) { + super(context); + } + + @SuppressWarnings("unused") + public void setColorValue(int colorValue) { + mColorValue = colorValue; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + paint.setColor(Color.rgb(mColorValue, 255 - mColorValue, 255)); + + for (int i = 0; i < 400; i++) { + canvas.drawRect(0, 0, getWidth(), getHeight(), paint); + } + } + } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + OverdrawView overdrawView = new OverdrawView(this); + setContentView(overdrawView); + + ObjectAnimator objectAnimator = ObjectAnimator.ofInt(overdrawView, "colorValue", 0, 255); + objectAnimator.setRepeatMode(ValueAnimator.REVERSE); + objectAnimator.setRepeatCount(ValueAnimator.INFINITE); + objectAnimator.start(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java b/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java new file mode 100644 index 0000000..a12742d --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.graphics.SurfaceTexture; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.Gravity; +import android.view.TextureView; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.android.test.uibench.opengl.ImageFlipRenderThread; + +public class GlTextureViewActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener { + private ImageFlipRenderThread mRenderThread; + private TextureView mTextureView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mTextureView = new TextureView(this); + mTextureView.setSurfaceTextureListener(this); + setContentView(mTextureView, new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, + Gravity.CENTER)); + } + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + mRenderThread = new ImageFlipRenderThread(getResources(), surface); + mRenderThread.start(); + + mTextureView.setCameraDistance(5000); + + ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f); + animator.setRepeatMode(ObjectAnimator.REVERSE); + animator.setRepeatCount(ObjectAnimator.INFINITE); + animator.setDuration(4000); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mTextureView.invalidate(); + } + }); + animator.start(); + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + mRenderThread.finish(); + try { + mRenderThread.join(); + } catch (InterruptedException e) { + Log.e(ImageFlipRenderThread.LOG_TAG, "Could not wait for render thread"); + } + return true; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + } + +}
\ No newline at end of file diff --git a/tests/UiBench/src/com/android/test/uibench/InflatingListActivity.java b/tests/UiBench/src/com/android/test/uibench/InflatingListActivity.java new file mode 100644 index 0000000..603244e --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/InflatingListActivity.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import com.android.test.uibench.listview.CompatListActivity; + +public class InflatingListActivity extends CompatListActivity { + @Override + protected ListAdapter createListAdapter() { + return new ArrayAdapter<String>(this, + android.R.layout.simple_list_item_1, TextUtils.buildSimpleStringList()) { + @Override + public View getView(int position, View convertView, ViewGroup parent) { + // pathological getView behavior: drop convertView on the floor to force inflation + return super.getView(position, null, parent); + } + }; + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java b/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java new file mode 100644 index 0000000..93d67a6 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.ColorInt; +import android.support.v7.app.AppCompatActivity; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +/** + * Tests invalidation performance by invalidating a large number of easily rendered views, + */ +public class InvalidateActivity extends AppCompatActivity { + public static class ColorView extends View { + @ColorInt + public int mColor; + + public ColorView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setColor(@ColorInt int color) { + mColor = color; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.drawColor(mColor); + } + } + + ColorView[][] mColorViews; + + @SuppressWarnings("unused") + public void setColorValue(int colorValue) { + @ColorInt int a = Color.rgb(colorValue, 255 - colorValue, 255); + @ColorInt int b = Color.rgb(255, colorValue, 255 - colorValue); + for (int y = 0; y < mColorViews.length; y++) { + for (int x = 0; x < mColorViews[y].length; x++) { + mColorViews[y][x].setColor((x + y) % 2 == 0 ? a : b); + } + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_invalidate); + + ViewGroup root = (ViewGroup) findViewById(R.id.invalidate_root); + for (int y = 0; y < root.getChildCount(); y++) { + ViewGroup row = (ViewGroup) root.getChildAt(y); + if (mColorViews == null) { + mColorViews = new ColorView[root.getChildCount()][row.getChildCount()]; + } + + for (int x = 0; x < row.getChildCount(); x++) { + mColorViews[y][x] = (ColorView) row.getChildAt(x); + } + } + + ObjectAnimator animator = ObjectAnimator.ofInt(this, "colorValue", 0, 255); + animator.setRepeatMode(ValueAnimator.REVERSE); + animator.setRepeatCount(ValueAnimator.INFINITE); + animator.start(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/MainActivity.java b/tests/UiBench/src/com/android/test/uibench/MainActivity.java new file mode 100644 index 0000000..2111274 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/MainActivity.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.ListFragment; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ListView; +import android.widget.SimpleAdapter; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MainActivity extends AppCompatActivity { + private static final String EXTRA_PATH = "activity_path"; + private static final String CATEGORY_HWUI_TEST = "com.android.test.uibench.TEST"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + String path = intent.getStringExtra(EXTRA_PATH); + + if (path == null) { + path = ""; + } else { + // not root level, display where we are in the hierarchy + setTitle(path); + } + + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { + ListFragment listFragment = new ListFragment() { + @Override + @SuppressWarnings("unchecked") + public void onListItemClick(ListView l, View v, int position, long id) { + Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position); + + Intent intent = (Intent) map.get("intent"); + startActivity(intent); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + getListView().setTextFilterEnabled(true); + } + }; + listFragment.setListAdapter(new SimpleAdapter(this, getData(path), + android.R.layout.simple_list_item_1, new String[] { "title" }, + new int[] { android.R.id.text1 })); + fm.beginTransaction().add(android.R.id.content, listFragment).commit(); + } + } + + protected List<Map<String, Object>> getData(String prefix) { + List<Map<String, Object>> myData = new ArrayList<>(); + + Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory(CATEGORY_HWUI_TEST); + + PackageManager pm = getPackageManager(); + List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0); + + if (null == list) + return myData; + + String[] prefixPath; + String prefixWithSlash = prefix; + + if (prefix.equals("")) { + prefixPath = null; + } else { + prefixPath = prefix.split("/"); + prefixWithSlash = prefix + "/"; + } + + int len = list.size(); + + Map<String, Boolean> entries = new HashMap<>(); + + for (int i = 0; i < len; i++) { + ResolveInfo info = list.get(i); + CharSequence labelSeq = info.loadLabel(pm); + String label = labelSeq != null + ? labelSeq.toString() + : info.activityInfo.name; + + if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) { + + String[] labelPath = label.split("/"); + + String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length]; + + if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) { + addItem(myData, nextLabel, activityIntent( + info.activityInfo.applicationInfo.packageName, + info.activityInfo.name)); + } else { + if (entries.get(nextLabel) == null) { + addItem(myData, nextLabel, browseIntent(prefix.equals("") ? + nextLabel : prefix + "/" + nextLabel)); + entries.put(nextLabel, true); + } + } + } + } + + Collections.sort(myData, sDisplayNameComparator); + + return myData; + } + + private final static Comparator<Map<String, Object>> sDisplayNameComparator = + new Comparator<Map<String, Object>>() { + private final Collator collator = Collator.getInstance(); + + public int compare(Map<String, Object> map1, Map<String, Object> map2) { + return collator.compare(map1.get("title"), map2.get("title")); + } + }; + + protected Intent activityIntent(String pkg, String componentName) { + Intent result = new Intent(); + result.setClassName(pkg, componentName); + return result; + } + + protected Intent browseIntent(String path) { + Intent result = new Intent(); + result.setClass(this, MainActivity.class); + result.putExtra(EXTRA_PATH, path); + return result; + } + + protected void addItem(List<Map<String, Object>> data, String name, Intent intent) { + Map<String, Object> temp = new HashMap<>(); + temp.put("title", name); + temp.put("intent", intent); + data.add(temp); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java new file mode 100644 index 0000000..d32f071 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.ListFragment; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ArrayAdapter; + +public class ShadowGridActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { + ListFragment listFragment = new ListFragment() { + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + getListView().setDivider(null); + } + }; + + listFragment.setListAdapter(new ArrayAdapter<>(this, + R.layout.card_row, R.id.card_text, TextUtils.buildSimpleStringList())); + fm.beginTransaction().add(android.R.id.content, listFragment).commit(); + } + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TextCacheHighHitrateActivity.java b/tests/UiBench/src/com/android/test/uibench/TextCacheHighHitrateActivity.java new file mode 100644 index 0000000..fc5be35 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TextCacheHighHitrateActivity.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import com.android.test.uibench.listview.CompatListActivity; + +public class TextCacheHighHitrateActivity extends CompatListActivity { + @Override + protected ListAdapter createListAdapter() { + return new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + TextUtils.buildParagraphListWithHitPercentage(80)); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TextCacheLowHitrateActivity.java b/tests/UiBench/src/com/android/test/uibench/TextCacheLowHitrateActivity.java new file mode 100644 index 0000000..14dc437 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TextCacheLowHitrateActivity.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import com.android.test.uibench.listview.CompatListActivity; + +public class TextCacheLowHitrateActivity extends CompatListActivity { + @Override + protected ListAdapter createListAdapter() { + return new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + TextUtils.buildParagraphListWithHitPercentage(20)); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TextUtils.java b/tests/UiBench/src/com/android/test/uibench/TextUtils.java new file mode 100644 index 0000000..d88ca1e --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TextUtils.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import java.util.Random; + +public class TextUtils { + private static final int STRING_COUNT = 200; + private static final int SIMPLE_STRING_LENGTH = 10; + + /** + * Create word of random assortment of lower/upper case letters + */ + private static String randomWord(Random random, int length) { + String result = ""; + for (int j = 0; j < length; j++) { + // add random letter + int base = random.nextInt(2) == 0 ? 'A' : 'a'; + result += (char)(random.nextInt(26) + base); + } + return result; + } + + public static String[] buildSimpleStringList() { + String[] strings = new String[STRING_COUNT]; + Random random = new Random(0); + for (int i = 0; i < strings.length; i++) { + strings[i] = randomWord(random, SIMPLE_STRING_LENGTH); + } + return strings; + } + + // a small number of strings reused frequently, expected to hit + // in the word-granularity text layout cache + static final String[] CACHE_HIT_STRINGS = new String[] { + "a", + "small", + "number", + "of", + "strings", + "reused", + "frequently" + }; + + private static final int WORDS_IN_PARAGRAPH = 150; + + // misses are fairly long 'words' to ensure they miss + private static final int PARAGRAPH_MISS_MIN_LENGTH = 4; + private static final int PARAGRAPH_MISS_MAX_LENGTH = 9; + + static String[] buildParagraphListWithHitPercentage(int hitPercentage) { + if (hitPercentage < 0 || hitPercentage > 100) throw new IllegalArgumentException(); + + String[] strings = new String[STRING_COUNT]; + Random random = new Random(0); + for (int i = 0; i < strings.length; i++) { + String result = ""; + for (int word = 0; word < WORDS_IN_PARAGRAPH; word++) { + if (word != 0) { + result += " "; + } + if (random.nextInt(100) < hitPercentage) { + // add a common word, which is very likely to hit in the cache + result += CACHE_HIT_STRINGS[random.nextInt(CACHE_HIT_STRINGS.length)]; + } else { + // construct a random word, which will *most likely* miss + int length = PARAGRAPH_MISS_MIN_LENGTH; + length += random.nextInt(PARAGRAPH_MISS_MAX_LENGTH - PARAGRAPH_MISS_MIN_LENGTH); + + result += randomWord(random, length); + } + } + strings[i] = result; + } + + return strings; + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TrivialAnimationActivity.java b/tests/UiBench/src/com/android/test/uibench/TrivialAnimationActivity.java new file mode 100644 index 0000000..6e98472 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TrivialAnimationActivity.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +public class TrivialAnimationActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setBackgroundDrawable(new ColorDrawable() { + int colorValue = 0; + int colorDelta = 1; + + @Override + public void draw(Canvas canvas) { + colorValue += colorDelta; + if (colorValue == 255 || colorValue == 0) { + colorDelta *= -1; + } + + setColor(Color.rgb(255, colorValue, 255 - colorValue)); + invalidateSelf(); + super.draw(canvas); + } + }); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java b/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java new file mode 100644 index 0000000..2625a99 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import com.android.test.uibench.listview.CompatListActivity; + +public class TrivialListActivity extends CompatListActivity { + @Override + protected ListAdapter createListAdapter() { + return new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + TextUtils.buildSimpleStringList()); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TrivialRecyclerViewActivity.java b/tests/UiBench/src/com/android/test/uibench/TrivialRecyclerViewActivity.java new file mode 100644 index 0000000..4647ba7 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TrivialRecyclerViewActivity.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2015 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.test.uibench; + +import android.support.v7.widget.RecyclerView; + +import com.android.test.uibench.recyclerview.RvArrayAdapter; +import com.android.test.uibench.recyclerview.RvCompatListActivity; + +public class TrivialRecyclerViewActivity extends RvCompatListActivity { + @Override + protected RecyclerView.Adapter createAdapter() { + return new RvArrayAdapter(TextUtils.buildSimpleStringList()); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java b/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java new file mode 100644 index 0000000..214c074 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 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.test.uibench.listview; + +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.ListFragment; +import android.support.v7.app.AppCompatActivity; +import android.widget.ListAdapter; + +public abstract class CompatListActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { + ListFragment listFragment = new ListFragment(); + listFragment.setListAdapter(createListAdapter()); + fm.beginTransaction().add(android.R.id.content, listFragment).commit(); + } + } + + protected abstract ListAdapter createListAdapter(); +} diff --git a/tests/UiBench/src/com/android/test/uibench/opengl/ImageFlipRenderThread.java b/tests/UiBench/src/com/android/test/uibench/opengl/ImageFlipRenderThread.java new file mode 100644 index 0000000..119ce52 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/opengl/ImageFlipRenderThread.java @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2015 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.test.uibench.opengl; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.SurfaceTexture; +import android.opengl.GLUtils; +import android.util.Log; + +import com.android.test.uibench.R; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; + +import static android.opengl.GLES20.GL_CLAMP_TO_EDGE; +import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; +import static android.opengl.GLES20.GL_COMPILE_STATUS; +import static android.opengl.GLES20.GL_FLOAT; +import static android.opengl.GLES20.GL_FRAGMENT_SHADER; +import static android.opengl.GLES20.GL_LINEAR; +import static android.opengl.GLES20.GL_LINK_STATUS; +import static android.opengl.GLES20.GL_NO_ERROR; +import static android.opengl.GLES20.GL_RGBA; +import static android.opengl.GLES20.GL_TEXTURE0; +import static android.opengl.GLES20.GL_TEXTURE_2D; +import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER; +import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER; +import static android.opengl.GLES20.GL_TEXTURE_WRAP_S; +import static android.opengl.GLES20.GL_TEXTURE_WRAP_T; +import static android.opengl.GLES20.GL_TRIANGLE_STRIP; +import static android.opengl.GLES20.GL_TRUE; +import static android.opengl.GLES20.GL_UNSIGNED_BYTE; +import static android.opengl.GLES20.GL_VERTEX_SHADER; +import static android.opengl.GLES20.glActiveTexture; +import static android.opengl.GLES20.glAttachShader; +import static android.opengl.GLES20.glBindTexture; +import static android.opengl.GLES20.glClear; +import static android.opengl.GLES20.glClearColor; +import static android.opengl.GLES20.glCompileShader; +import static android.opengl.GLES20.glCreateProgram; +import static android.opengl.GLES20.glCreateShader; +import static android.opengl.GLES20.glDeleteProgram; +import static android.opengl.GLES20.glDeleteShader; +import static android.opengl.GLES20.glDrawArrays; +import static android.opengl.GLES20.glEnableVertexAttribArray; +import static android.opengl.GLES20.glGenTextures; +import static android.opengl.GLES20.glGetAttribLocation; +import static android.opengl.GLES20.glGetError; +import static android.opengl.GLES20.glGetProgramInfoLog; +import static android.opengl.GLES20.glGetProgramiv; +import static android.opengl.GLES20.glGetShaderInfoLog; +import static android.opengl.GLES20.glGetShaderiv; +import static android.opengl.GLES20.glGetUniformLocation; +import static android.opengl.GLES20.glLinkProgram; +import static android.opengl.GLES20.glShaderSource; +import static android.opengl.GLES20.glTexParameteri; +import static android.opengl.GLES20.glUniform1i; +import static android.opengl.GLES20.glUseProgram; +import static android.opengl.GLES20.glVertexAttribPointer; + +public class ImageFlipRenderThread extends Thread { + public static final String LOG_TAG = "GLTextureView"; + + static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + static final int EGL_OPENGL_ES2_BIT = 4; + + private volatile boolean mFinished; + + private final Resources mResources; + private final SurfaceTexture mSurface; + + private EGL10 mEgl; + private EGLDisplay mEglDisplay; + private EGLConfig mEglConfig; + private EGLContext mEglContext; + private EGLSurface mEglSurface; + + public ImageFlipRenderThread(Resources resources, SurfaceTexture surface) { + mResources = resources; + mSurface = surface; + } + + private static final String sSimpleVS = + "attribute vec4 position;\n" + + "attribute vec2 texCoords;\n" + + "varying vec2 outTexCoords;\n" + + "\nvoid main(void) {\n" + + " outTexCoords = texCoords;\n" + + " gl_Position = position;\n" + + "}\n\n"; + private static final String sSimpleFS = + "precision mediump float;\n\n" + + "varying vec2 outTexCoords;\n" + + "uniform sampler2D texture;\n" + + "\nvoid main(void) {\n" + + " gl_FragColor = texture2D(texture, outTexCoords);\n" + + "}\n\n"; + + private static final int FLOAT_SIZE_BYTES = 4; + private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; + private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; + private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; + private final float[] mTriangleVerticesData = { + // X, Y, Z, U, V + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + }; + + @Override + public void run() { + initGL(); + + FloatBuffer triangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length + * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); + triangleVertices.put(mTriangleVerticesData).position(0); + + int texture = loadTexture(R.drawable.large_photo); + int program = buildProgram(sSimpleVS, sSimpleFS); + + int attribPosition = glGetAttribLocation(program, "position"); + checkGlError(); + + int attribTexCoords = glGetAttribLocation(program, "texCoords"); + checkGlError(); + + int uniformTexture = glGetUniformLocation(program, "texture"); + checkGlError(); + + glBindTexture(GL_TEXTURE_2D, texture); + checkGlError(); + + glUseProgram(program); + checkGlError(); + + glEnableVertexAttribArray(attribPosition); + checkGlError(); + + glEnableVertexAttribArray(attribTexCoords); + checkGlError(); + + glUniform1i(uniformTexture, 0); + checkGlError(); + + // drawQuad + triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); + glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false, + TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); + checkGlError(); + + triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); + glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false, + TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); + checkGlError(); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + checkGlError(); + + while (!mFinished) { + checkCurrent(); + + glClear(GL_COLOR_BUFFER_BIT); + checkGlError(); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + checkGlError(); + + if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { + throw new RuntimeException("Cannot swap buffers"); + } + checkEglError(); + + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + // Ignore + } + } + + finishGL(); + } + + private int loadTexture(int resource) { + int[] textures = new int[1]; + + glActiveTexture(GL_TEXTURE0); + glGenTextures(1, textures, 0); + checkGlError(); + + int texture = textures[0]; + glBindTexture(GL_TEXTURE_2D, texture); + checkGlError(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource); + + GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0); + checkGlError(); + + bitmap.recycle(); + + return texture; + } + + private static int buildProgram(String vertex, String fragment) { + int vertexShader = buildShader(vertex, GL_VERTEX_SHADER); + if (vertexShader == 0) return 0; + + int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); + if (fragmentShader == 0) return 0; + + int program = glCreateProgram(); + glAttachShader(program, vertexShader); + checkGlError(); + + glAttachShader(program, fragmentShader); + checkGlError(); + + glLinkProgram(program); + checkGlError(); + + int[] status = new int[1]; + glGetProgramiv(program, GL_LINK_STATUS, status, 0); + if (status[0] != GL_TRUE) { + String error = glGetProgramInfoLog(program); + Log.d(LOG_TAG, "Error while linking program:\n" + error); + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + glDeleteProgram(program); + return 0; + } + + return program; + } + + private static int buildShader(String source, int type) { + int shader = glCreateShader(type); + + glShaderSource(shader, source); + checkGlError(); + + glCompileShader(shader); + checkGlError(); + + int[] status = new int[1]; + glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0); + if (status[0] != GL_TRUE) { + String error = glGetShaderInfoLog(shader); + Log.d(LOG_TAG, "Error while compiling shader:\n" + error); + glDeleteShader(shader); + return 0; + } + + return shader; + } + + private void checkEglError() { + int error = mEgl.eglGetError(); + if (error != EGL10.EGL_SUCCESS) { + Log.w(LOG_TAG, "EGL error = 0x" + Integer.toHexString(error)); + } + } + + private static void checkGlError() { + int error = glGetError(); + if (error != GL_NO_ERROR) { + Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error)); + } + } + + private void finishGL() { + mEgl.eglDestroyContext(mEglDisplay, mEglContext); + mEgl.eglDestroySurface(mEglDisplay, mEglSurface); + } + + private void checkCurrent() { + if (!mEglContext.equals(mEgl.eglGetCurrentContext()) || + !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + throw new RuntimeException("eglMakeCurrent failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + } + } + + private void initGL() { + mEgl = (EGL10) EGLContext.getEGL(); + + mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { + throw new RuntimeException("eglGetDisplay failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + + int[] version = new int[2]; + if (!mEgl.eglInitialize(mEglDisplay, version)) { + throw new RuntimeException("eglInitialize failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + + mEglConfig = chooseEglConfig(); + if (mEglConfig == null) { + throw new RuntimeException("eglConfig not initialized"); + } + + mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); + + mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null); + + if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { + int error = mEgl.eglGetError(); + if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { + Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); + return; + } + throw new RuntimeException("createWindowSurface failed " + + GLUtils.getEGLErrorString(error)); + } + + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + throw new RuntimeException("eglMakeCurrent failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + } + + + EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { + int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE}; + return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); + } + + private EGLConfig chooseEglConfig() { + int[] configsCount = new int[1]; + EGLConfig[] configs = new EGLConfig[1]; + int[] configSpec = getConfig(); + if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { + throw new IllegalArgumentException("eglChooseConfig failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } else if (configsCount[0] > 0) { + return configs[0]; + } + return null; + } + + private static int[] getConfig() { + return new int[]{ + EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL10.EGL_RED_SIZE, 8, + EGL10.EGL_GREEN_SIZE, 8, + EGL10.EGL_BLUE_SIZE, 8, + EGL10.EGL_ALPHA_SIZE, 8, + EGL10.EGL_DEPTH_SIZE, 0, + EGL10.EGL_STENCIL_SIZE, 0, + EGL10.EGL_NONE + }; + } + + public void finish() { + mFinished = true; + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvArrayAdapter.java b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvArrayAdapter.java new file mode 100644 index 0000000..e5a3a49 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvArrayAdapter.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015 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.test.uibench.recyclerview; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class RvArrayAdapter extends RecyclerView.Adapter<RvArrayAdapter.ViewHolder> { + private String[] mDataSet; + private LayoutInflater mLayoutInflater; + + public static class ViewHolder extends RecyclerView.ViewHolder { + private final TextView mTextView; + + public ViewHolder(View v) { + super(v); + mTextView = (TextView) v.findViewById(android.R.id.text1); + } + + public TextView getTextView() { + return mTextView; + } + } + + public RvArrayAdapter(String[] dataSet) { + mDataSet = dataSet; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + if (mLayoutInflater == null) { + mLayoutInflater = LayoutInflater.from(viewGroup.getContext()); + } + View v = mLayoutInflater.inflate(android.R.layout.simple_list_item_1, viewGroup, false); + + return new ViewHolder(v); + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, final int position) { + viewHolder.getTextView().setText(mDataSet[position]); + } + + @Override + public int getItemCount() { + return mDataSet.length; + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java new file mode 100644 index 0000000..e08dbc6 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 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.test.uibench.recyclerview; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; + +import com.android.test.uibench.R; + +public abstract class RvCompatListActivity extends AppCompatActivity { + public static class RecyclerViewFragment extends Fragment { + RecyclerView.LayoutManager layoutManager; + RecyclerView.Adapter adapter; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + RecyclerView recyclerView = (RecyclerView) inflater.inflate( + R.layout.recycler_view, container, false); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(adapter); + return recyclerView; + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { + RecyclerViewFragment fragment = new RecyclerViewFragment(); + fragment.layoutManager = createLayoutManager(this); + fragment.adapter = createAdapter(); + fm.beginTransaction().add(android.R.id.content, fragment).commit(); + } + } + + protected RecyclerView.LayoutManager createLayoutManager(Context context) { + return new LinearLayoutManager(context); + } + + protected abstract RecyclerView.Adapter createAdapter(); +} |