Merge "Add projection tests to CtsVerifier Bug: 13598201 Change-Id: I8faf7761efe4dfecb164dbf18c01c7cedabe5d11" into lmp-dev
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index c227665a..4b75be2 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -21,7 +21,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := cts-sensors-tests
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 3373ef1..5708a50 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -967,6 +967,55 @@
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false" />
+ <activity android:name=".projection.cube.ProjectionCubeActivity"
+ android:label="@string/pca_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+ </activity>
+
+ <activity android:name=".projection.widgets.ProjectionWidgetActivity"
+ android:label="@string/pwa_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+ </activity>
+
+ <activity android:name=".projection.list.ProjectionListActivity"
+ android:label="@string/pla_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+ </activity>
+
+ <activity android:name=".projection.video.ProjectionVideoActivity"
+ android:label="@string/pva_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+ </activity>
+
+ <activity android:name=".projection.touch.ProjectionTouchActivity"
+ android:label="@string/pta_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+ </activity>
+
+ <service android:name=".projection.ProjectionService"
+ android:label="@string/projection_service_name"
+ android:process=":projectionservice" />
+
</application>
</manifest>
diff --git a/apps/CtsVerifier/res/layout/pa_main.xml b/apps/CtsVerifier/res/layout/pa_main.xml
new file mode 100644
index 0000000..b6b8e4b
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pa_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextureView
+ android:id="@+id/texture_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <include layout="@layout/pass_fail_buttons" />
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/pca_cubes.xml b/apps/CtsVerifier/res/layout/pca_cubes.xml
new file mode 100644
index 0000000..25869b9
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pca_cubes.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true" >
+
+ <android.opengl.GLSurfaceView
+ android:id="@+id/cube_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/pla_list.xml b/apps/CtsVerifier/res/layout/pla_list.xml
new file mode 100644
index 0000000..0973136
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pla_list.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <ListView
+ android:id="@+id/pla_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ </ListView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/pta_touch.xml b/apps/CtsVerifier/res/layout/pta_touch.xml
new file mode 100644
index 0000000..8cf6e89
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pta_touch.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ <com.android.cts.verifier.projection.touch.TouchPointView
+ android:id="@+id/multi_touch_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/pva_video.xml b/apps/CtsVerifier/res/layout/pva_video.xml
new file mode 100644
index 0000000..a62c833
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pva_video.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <VideoView
+ android:id="@+id/video_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/pwa_buttons.xml b/apps/CtsVerifier/res/layout/pwa_buttons.xml
new file mode 100644
index 0000000..fc2d10f
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pwa_buttons.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="bottom"
+ android:orientation="vertical" >
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/pwa_button" />
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/pwa_button" />
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/pwa_button" />
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/pwa_button" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/pwa_widgets.xml b/apps/CtsVerifier/res/layout/pwa_widgets.xml
new file mode 100644
index 0000000..4bfcec6
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pwa_widgets.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextureView
+ android:id="@+id/texture_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <include layout="@layout/pass_fail_buttons" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <Button
+ android:id="@+id/up_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/pwa_button_up" />
+
+ <Button
+ android:id="@+id/down_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/pwa_button_down" />
+
+ <Button
+ android:id="@+id/left_button"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:text="@string/pwa_button_left" />
+
+ <Button
+ android:id="@+id/right_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/pwa_button_right" />
+
+ </LinearLayout>
+ </LinearLayout>
+
+</FrameLayout>
diff --git a/apps/CtsVerifier/res/raw/test_video.mp4 b/apps/CtsVerifier/res/raw/test_video.mp4
new file mode 100644
index 0000000..ab95ac0
--- /dev/null
+++ b/apps/CtsVerifier/res/raw/test_video.mp4
Binary files differ
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index d7e6d33..86729ad 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -961,7 +961,6 @@
2. Verify that a timer is started and the timers UI is shown with a timer named "Start Timer Test".\n
3. Verify that the timer rings after 30 seconds.\n
</string>
-
<!-- Strings for LockConfirmBypassTest -->
<string name="lock_confirm_test_title">Keyguard Password Verification</string>
<string name="lock_set_button_text">Set password</string>
@@ -972,4 +971,31 @@
\nThen click the \"Change password\" button to change it. You should be prompted for the current password first. If you are not, then mark the test as failed.
</string>
+ <!-- String for Projection Tests -->
+ <string name="test_category_projection">Projection Tests</string>
+ <string name="projection_service_name">Projection Service</string>
+ <string name="pca_info">This tests whether or not OpenGL projection works.\n
+ You should see two "tumbling cubes." Tapping the screen should case the cubes to explode.</string>
+ <string name="pca_test">Projection Cube Test</string>
+ <string name="pwa_info">This tests whether or displaying widets and keyfocus navigation works.\n
+ You should see four buttons on the bottom of the screen.\n
+ Pressing the "up" and "down" buttons should highlight different buttons.\n
+ Further, you should also be able to touch them and they should highlight as ususual.</string>
+ <string name="pwa_test">Projection Widget Test</string>
+ <string name="pwa_button_up">Up</string>
+ <string name="pwa_button_down">Down</string>
+ <string name="pwa_button_left">Left</string>
+ <string name="pwa_button_right">Right</string>
+ <string name="pwa_button">Button</string>
+ <string name="pla_test">Projection Scrolling List Test</string>
+ <string name="pla_info">This tests whether a projected list view will scroll properly\n
+ You should see 50 list items and be able to scroll up and down the list</string>
+ <string name="pva_test">Projection Video Playback Test</string>
+ <string name="pva_info">This tests whether video playback works when projected.\n
+ You should see a blinking white box and here a beep that is synchronized with each blink</string>
+ <string name="pta_test">Projection Multitouch Test</string>
+ <string name="pta_info">This tests whether multitouch works.\n
+ Touching the screen should render a dot at the location you touched.\n
+ Touching with additional fingers will render additoinal dots and you should be able to drag them around.</string>
+
</resources>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/IProjectionService.aidl b/apps/CtsVerifier/src/com/android/cts/verifier/projection/IProjectionService.aidl
new file mode 100644
index 0000000..0bc1b20
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/IProjectionService.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.cts.verifier.projection;
+
+import android.view.Surface;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+interface IProjectionService {
+ void startRendering(in Surface surface, int width, int height, int density, int viewType);
+ void stopRendering();
+ void onTouchEvent(in MotionEvent event);
+ void onKeyEvent(in KeyEvent event);
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectedPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectedPresentation.java
new file mode 100644
index 0000000..4990ed4
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectedPresentation.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection;
+
+import android.app.Presentation;
+import android.content.Context;
+import android.view.Display;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+
+/**
+ * Base class for Presentations which are to be projected onto a VirtualDisplay
+ */
+public abstract class ProjectedPresentation extends Presentation {
+ public ProjectedPresentation(Context outerContext, Display display) {
+ // This theme is required to prevent an extra view from obscuring the presentation
+ super(outerContext, display, android.R.style.Theme_Holo_Light_NoActionBar_TranslucentDecor);
+
+ getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
+
+ // So we can control the input
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+ }
+
+ public void injectTouchEvent(MotionEvent event) {
+ getWindow().setLocalFocus(true, true);
+ getWindow().injectInputEvent(event);
+ }
+
+ public void injectKeyEvent(KeyEvent event) {
+ getWindow().setLocalFocus(true, false);
+ getWindow().injectInputEvent(event);
+ }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionActivity.java
new file mode 100644
index 0000000..18d9d43
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionActivity.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.cts.verifier.projection;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.TextureView;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+/**
+ * Base activity for each projection test case. Handles the service connection and TextureView
+ * listeners
+ */
+public abstract class ProjectionActivity extends PassFailButtons.Activity
+ implements TextureView.SurfaceTextureListener {
+ private static final String TAG = ProjectionActivity.class.getSimpleName();
+ protected Intent mStartIntent;
+ protected TextureView mTextureView;
+ protected volatile Surface mSurface;
+ protected int mWidth;
+ protected int mHeight;
+ protected ProjectionPresentationType mType;
+
+ protected IProjectionService mService;
+ protected final ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ mService = IProjectionService.Stub.asInterface(binder);
+ new Handler().post(new Runnable() {
+
+ @Override
+ public void run() {
+ Log.i(TAG, "onServiceConnected thread " + Thread.currentThread());
+ DisplayMetrics metrics = ProjectionActivity.this.getResources().getDisplayMetrics();
+ try {
+ mService.startRendering(mSurface, mWidth, mHeight, metrics.densityDpi, mType.ordinal());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to execute startRendering", e);
+ }
+ }
+
+ });
+
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mService = null;
+ }
+
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i(TAG, "onCreate");
+ mStartIntent = new Intent(this, ProjectionService.class);
+
+ }
+
+ protected View setContentViewAndInfoResources(int layoutId, int titleId, int infoId) {
+ View view = getLayoutInflater().inflate(layoutId, null);
+ setContentView(view);
+
+ mTextureView = (TextureView) view.findViewById(R.id.texture_view);
+ mTextureView.setSurfaceTextureListener(this);
+ mTextureView.setOnTouchListener(new OnTouchListener() {
+
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ if (mService != null) {
+ try {
+ mService.onTouchEvent(event);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to execute onTouchEvent", e);
+ }
+ }
+ return true;
+ }
+
+ });
+
+ setInfoResources(titleId, infoId, -1);
+ setPassFailButtonClickListeners();
+ return view;
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ Log.i(TAG, "onSurfaceTextureAvailable " + "w: " + width + " h: " + height);
+ mSurface = new Surface(surface);
+ mWidth = width;
+ mHeight = height;
+ if (mService == null) {
+ bindService(mStartIntent, mConnection,
+ Context.BIND_AUTO_CREATE);
+ }
+
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ Log.i(TAG, "onSurfaceTextureDestroyed");
+ if (mService != null) {
+ try {
+ mService.stopRendering();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to execute stopRendering", e);
+ }
+ }
+ mSurface.release();
+ mSurface = null;
+
+ unbindService(mConnection);
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ Log.i(TAG, "onSurfaceTextureSizeChanged " + surface.toString() + "w: " + width + " h: "
+ + height);
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ Log.i(TAG, "onSurfaceTextureUpdated " + surface.toString());
+ }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionPresentationType.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionPresentationType.java
new file mode 100644
index 0000000..28f5d46
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionPresentationType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection;
+
+public enum ProjectionPresentationType {
+ TUMBLING_CUBES,
+ BASIC_WIDGETS,
+ MULTI_TOUCH,
+ SCROLLING_LIST,
+ VIDEO_PLAYBACK
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionService.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionService.java
new file mode 100644
index 0000000..bfe5a30
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionService.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection;
+
+import android.app.Service;
+import android.content.Intent;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.Surface;
+
+import com.android.cts.verifier.projection.cube.CubePresentation;
+import com.android.cts.verifier.projection.list.ListPresentation;
+import com.android.cts.verifier.projection.touch.TouchPresentation;
+import com.android.cts.verifier.projection.video.VideoPresentation;
+import com.android.cts.verifier.projection.widgets.WidgetPresentation;
+
+/**
+ * Service to handle rendering of views on a virtual display and to forward input events to the
+ * display
+ */
+public class ProjectionService extends Service {
+ private final String TAG = ProjectionService.class.getSimpleName();
+ private final String DISPLAY_NAME = "CtsVerifier Virtual Display";
+
+ private Handler mUIHandler;
+
+ private ProjectedPresentation createPresentation(int typeOrdinal) {
+ ProjectionPresentationType type = ProjectionPresentationType.values()[typeOrdinal];
+ switch (type) {
+ case TUMBLING_CUBES:
+ return new CubePresentation(ProjectionService.this, mDisplay.getDisplay());
+
+ case BASIC_WIDGETS:
+ return new WidgetPresentation(ProjectionService.this, mDisplay.getDisplay());
+
+ case SCROLLING_LIST:
+ return new ListPresentation(ProjectionService.this, mDisplay.getDisplay());
+
+ case VIDEO_PLAYBACK:
+ return new VideoPresentation(ProjectionService.this, mDisplay.getDisplay());
+
+ case MULTI_TOUCH:
+ return new TouchPresentation(ProjectionService.this, mDisplay.getDisplay());
+ }
+
+ return null;
+ }
+
+ private class ProjectionServiceBinder extends IProjectionService.Stub {
+ @Override
+ public void startRendering(final Surface surface, final int width, final int height,
+ final int density,
+ final int viewType) throws RemoteException {
+ mUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ DisplayManager manager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
+ Log.i(TAG, "Surface " + surface.toString() + ": "
+ + Boolean.toString(surface.isValid()));
+ mDisplay = manager.createVirtualDisplay(DISPLAY_NAME, width, height, density,
+ surface, 0);
+ mPresentation = createPresentation(viewType);
+ if (mPresentation == null) {
+ return;
+ }
+
+ mPresentation.show();
+ }
+ });
+ }
+
+ @Override
+ public void stopRendering() throws RemoteException {
+ mUIHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ if (mPresentation != null) {
+ mPresentation.dismiss();
+ mPresentation = null;
+ }
+ }
+
+ });
+ }
+
+ @Override
+ public void onTouchEvent(final MotionEvent event) throws RemoteException {
+ mUIHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ if (mPresentation != null) {
+ mPresentation.injectTouchEvent(event);
+ }
+ }
+
+ });
+ }
+
+ @Override
+ public void onKeyEvent(final KeyEvent event) throws RemoteException {
+ mUIHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ if (mPresentation != null) {
+ mPresentation.injectKeyEvent(event);
+ }
+ }
+
+ });
+ }
+ }
+
+ private final IBinder mBinder = new ProjectionServiceBinder();
+ private VirtualDisplay mDisplay;
+ private ProjectedPresentation mPresentation;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.i(TAG, "onBind");
+ mUIHandler = new Handler(Looper.getMainLooper());
+ return mBinder;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/Cube.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/Cube.java
new file mode 100644
index 0000000..0b521fb
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/Cube.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.cube;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A vertex shaded cube.
+ */
+class Cube
+{
+ public Cube()
+ {
+ int one = 0x10000;
+ int vertices[] = {
+ -one, -one, -one,
+ one, -one, -one,
+ one, one, -one,
+ -one, one, -one,
+ -one, -one, one,
+ one, -one, one,
+ one, one, one,
+ -one, one, one,
+ };
+
+ int colors[] = {
+ 0, 0, 0, one,
+ one, 0, 0, one,
+ one, one, 0, one,
+ 0, one, 0, one,
+ 0, 0, one, one,
+ one, 0, one, one,
+ one, one, one, one,
+ 0, one, one, one,
+ };
+
+ byte indices[] = {
+ 0, 4, 5, 0, 5, 1,
+ 1, 5, 6, 1, 6, 2,
+ 2, 6, 7, 2, 7, 3,
+ 3, 7, 4, 3, 4, 0,
+ 4, 7, 6, 4, 6, 5,
+ 3, 0, 1, 3, 1, 2
+ };
+
+ // Buffers to be passed to gl*Pointer() functions
+ // must be direct, i.e., they must be placed on the
+ // native heap where the garbage collector cannot
+ // move them.
+ //
+ // Buffers with multi-byte datatypes (e.g., short, int, float)
+ // must have their byte order set to native order
+
+ ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
+ vbb.order(ByteOrder.nativeOrder());
+ mVertexBuffer = vbb.asIntBuffer();
+ mVertexBuffer.put(vertices);
+ mVertexBuffer.position(0);
+
+ ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
+ cbb.order(ByteOrder.nativeOrder());
+ mColorBuffer = cbb.asIntBuffer();
+ mColorBuffer.put(colors);
+ mColorBuffer.position(0);
+
+ mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
+ mIndexBuffer.put(indices);
+ mIndexBuffer.position(0);
+ }
+
+ public void draw(GL10 gl)
+ {
+ gl.glFrontFace(GL10.GL_CW);
+ gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
+ gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
+ gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
+ }
+
+ private IntBuffer mVertexBuffer;
+ private IntBuffer mColorBuffer;
+ private ByteBuffer mIndexBuffer;
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubePresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubePresentation.java
new file mode 100644
index 0000000..bf7825b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubePresentation.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.cube;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+
+
+
+/**
+ * Render tumbling cubes
+ *
+ */
+public class CubePresentation extends ProjectedPresentation {
+ public CubePresentation(Context context, Display display) {
+ super(context, display);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ View view = getLayoutInflater().inflate(R.layout.pca_cubes, null);
+ setContentView(view);
+
+ GLSurfaceView cubeView = (GLSurfaceView) view.findViewById(R.id.cube_view);
+ final CubeRenderer renderer = new CubeRenderer(true);
+ cubeView.setRenderer(renderer);
+
+ cubeView.setOnTouchListener(new OnTouchListener() {
+
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ renderer.explode();
+ return true;
+ }
+ });
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubeRenderer.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubeRenderer.java
new file mode 100644
index 0000000..9205fec
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubeRenderer.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.cube;
+
+import android.opengl.GLSurfaceView;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * Render a pair of tumbling cubes.
+ */
+public class CubeRenderer implements GLSurfaceView.Renderer {
+
+ private final boolean mTranslucentBackground;
+
+ private final Cube mCube;
+ private float mAngle;
+ private float mScale = 1.0f;
+ private boolean mExploding;
+
+ public CubeRenderer(boolean useTranslucentBackground) {
+ mTranslucentBackground = useTranslucentBackground;
+ mCube = new Cube();
+ }
+
+ public void explode() {
+ mExploding = true;
+ }
+
+ @Override
+ public void onDrawFrame(GL10 gl) {
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear().
+ */
+
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D objects
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0, 0, -3.0f);
+ gl.glRotatef(mAngle, 0, 1, 0);
+ gl.glRotatef(mAngle*0.25f, 1, 0, 0);
+
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+ gl.glScalef(mScale, mScale, mScale);
+ mCube.draw(gl);
+
+ gl.glRotatef(mAngle*2.0f, 0, 1, 1);
+ gl.glTranslatef(0.5f, 0.5f, 0.5f);
+
+ mCube.draw(gl);
+
+ mAngle += 1.2f;
+
+ if (mExploding) {
+ mScale *= 1.02f;
+ if (mScale > 4.0f) {
+ mScale = 1.0f;
+ mExploding = false;
+ }
+ }
+ }
+
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ gl.glViewport(0, 0, width, height);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to
+ * be set when the viewport is resized.
+ */
+
+ float ratio = (float) width / height;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+ }
+
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ /*
+ * Some one-time OpenGL initialization can be made here
+ * probably based on features of this particular context
+ */
+ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+ GL10.GL_FASTEST);
+
+ if (mTranslucentBackground) {
+ gl.glClearColor(0,0,0,0);
+ } else {
+ gl.glClearColor(1,1,1,1);
+ }
+ gl.glEnable(GL10.GL_CULL_FACE);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/ProjectionCubeActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/ProjectionCubeActivity.java
new file mode 100644
index 0000000..0ef9a30
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/ProjectionCubeActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.cube;
+
+import com.android.cts.verifier.R;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+
+public class ProjectionCubeActivity extends ProjectionActivity {
+ private static final String TAG = ProjectionCubeActivity.class.getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i(TAG, "onCreate");
+ setContentViewAndInfoResources(R.layout.pa_main, R.string.pca_test, R.string.pca_info);
+ mType = ProjectionPresentationType.TUMBLING_CUBES;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ListPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ListPresentation.java
new file mode 100644
index 0000000..dad4945
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ListPresentation.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.list;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+
+import java.util.ArrayList;
+
+/**
+ * Render a list view that scrolls
+ */
+public class ListPresentation extends ProjectedPresentation {
+ private ArrayList<String> mItemList = new ArrayList<String>();
+ private static final int NUM_ITEMS = 50; // Enough to make the list scroll
+
+ /**
+ * @param outerContext
+ * @param display
+ */
+ public ListPresentation(Context outerContext, Display display) {
+ super(outerContext, display);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ View view = getLayoutInflater().inflate(R.layout.pla_list, null);
+ setContentView(view);
+
+ for (int i = 0; i < NUM_ITEMS; ++i) {
+ mItemList.add("Item #" + i);
+ }
+
+ ListView listView = (ListView) view.findViewById(R.id.pla_list);
+
+ listView.setAdapter(new ArrayAdapter<String>(getContext(),
+ android.R.layout.simple_list_item_1, mItemList));
+ }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ProjectionListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ProjectionListActivity.java
new file mode 100644
index 0000000..c166320
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ProjectionListActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.list;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+import com.android.cts.verifier.projection.cube.ProjectionCubeActivity;
+
+public class ProjectionListActivity extends ProjectionActivity {
+ private static final String TAG = ProjectionCubeActivity.class.getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i(TAG, "onCreate");
+ setContentViewAndInfoResources(R.layout.pa_main, R.string.pla_test, R.string.pla_info);
+ mType = ProjectionPresentationType.SCROLLING_LIST;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/ProjectionTouchActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/ProjectionTouchActivity.java
new file mode 100644
index 0000000..ed1d881
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/ProjectionTouchActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.touch;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+import com.android.cts.verifier.projection.cube.ProjectionCubeActivity;
+
+public class ProjectionTouchActivity extends ProjectionActivity {
+ private static final String TAG = ProjectionCubeActivity.class.getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i(TAG, "onCreate");
+ setContentViewAndInfoResources(R.layout.pa_main, R.string.pta_test, R.string.pta_info);
+ mType = ProjectionPresentationType.MULTI_TOUCH;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPointView.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPointView.java
new file mode 100644
index 0000000..c88fd79
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPointView.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.touch;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+/*
+ * Simple view that draws a circle where a touch is registered
+ */
+public class TouchPointView extends View {
+ @SuppressWarnings("unused")
+ private static final String TAG = TouchPointView.class.getSimpleName();
+
+ private final int[] mColors = {
+ Color.RED,
+ Color.GREEN,
+ Color.BLUE,
+ Color.YELLOW,
+ Color.MAGENTA,
+ Color.BLACK,
+ Color.DKGRAY
+ };
+ List<Finger> mFingers;
+ Paint mPaint;
+
+ public TouchPointView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TouchPointView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mFingers = new ArrayList<Finger>();
+
+ mPaint = new Paint();
+ mPaint.setStyle(Paint.Style.FILL);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ mFingers.clear();
+ if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ invalidate();
+ return true;
+ }
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ int pointerId = event.getPointerId(i);
+ int pointerIndex = event.findPointerIndex(pointerId);
+ Finger finger = new Finger();
+ finger.point = new Point((int)event.getX(pointerIndex), (int)event.getY(pointerIndex));
+ finger.pointerId = pointerId;
+
+ mFingers.add(finger);
+ }
+ invalidate();
+ return true;
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ int radius = canvas.getWidth() / 20;
+ for (int i = 0; i < mFingers.size(); i++) {
+ Finger finger = mFingers.get(i);
+ Point point = finger.point;
+ int color = mColors[finger.pointerId % mColors.length];
+ mPaint.setColor(color);
+ canvas.drawCircle(point.x, point.y, radius, mPaint);
+ }
+ }
+
+ private class Finger {
+ public Point point;
+ public int pointerId;
+ }
+}
+
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/ProjectionVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/ProjectionVideoActivity.java
new file mode 100644
index 0000000..7a32b27
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/ProjectionVideoActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.video;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+
+public class ProjectionVideoActivity extends ProjectionActivity {
+ private static final String TAG = ProjectionVideoActivity.class.getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i(TAG, "onCreate");
+ setContentViewAndInfoResources(R.layout.pa_main, R.string.pva_test, R.string.pva_info);
+ mType = ProjectionPresentationType.VIDEO_PLAYBACK;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/VideoPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/VideoPresentation.java
new file mode 100644
index 0000000..4275cb8
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/VideoPresentation.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.video;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.View;
+import android.widget.VideoView;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+
+/**
+ * Play a test video that determines if the video and audio are in sync in projected presentations
+ */
+public class VideoPresentation extends ProjectedPresentation {
+
+ /**
+ * @param outerContext
+ * @param display
+ */
+ public VideoPresentation(Context outerContext, Display display) {
+ super(outerContext, display);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ View view = getLayoutInflater().inflate(R.layout.pva_video, null);
+ setContentView(view);
+ VideoView videoView = (VideoView) view.findViewById(R.id.video_view);
+ videoView.setOnPreparedListener(new OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ mp.setLooping(true);
+ }
+ });
+ String packageName = getContext().getPackageName();
+ Uri uri = Uri.parse("android.resource://" + packageName + "/" + R.raw.test_video);
+ videoView.setVideoURI(uri);
+ videoView.start();
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/ProjectionWidgetActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/ProjectionWidgetActivity.java
new file mode 100644
index 0000000..9b862de
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/ProjectionWidgetActivity.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.widgets;
+
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+
+public class ProjectionWidgetActivity extends ProjectionActivity {
+ private static final String TAG = ProjectionWidgetActivity.class.getSimpleName();
+
+ private class InjectDPadClickListener implements OnClickListener {
+ private int mKeyCode;
+
+ InjectDPadClickListener(int keyCode) {
+ mKeyCode = keyCode;
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mService != null) {
+ try {
+ mService.onKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, mKeyCode));
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error executing onKeyEvent", e);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ View view = setContentViewAndInfoResources(R.layout.pwa_widgets, R.string.pwa_test,
+ R.string.pwa_info);
+
+ mType = ProjectionPresentationType.BASIC_WIDGETS;
+
+ Button button;
+ {
+ button = (Button) view.findViewById(R.id.up_button);
+ button.setOnClickListener(new InjectDPadClickListener(KeyEvent.KEYCODE_DPAD_UP));
+ }
+ {
+ button = (Button) view.findViewById(R.id.down_button);
+ button.setOnClickListener(new InjectDPadClickListener(KeyEvent.KEYCODE_DPAD_DOWN));
+ }
+ {
+ button = (Button) view.findViewById(R.id.right_button);
+ button.setOnClickListener(new InjectDPadClickListener(KeyEvent.KEYCODE_DPAD_RIGHT));
+ }
+ {
+ button = (Button) view.findViewById(R.id.left_button);
+ button.setOnClickListener(new InjectDPadClickListener(KeyEvent.KEYCODE_DPAD_LEFT));
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/WidgetPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/WidgetPresentation.java
new file mode 100644
index 0000000..8af2757
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/WidgetPresentation.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.projection.widgets;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Display;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+
+/**
+ * Check if widgets display and that key focus works in projected mode
+ */
+public class WidgetPresentation extends ProjectedPresentation {
+
+ /**
+ * @param outerContext
+ * @param display
+ */
+ public WidgetPresentation(Context outerContext, Display display) {
+ super(outerContext, display);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.pwa_buttons);
+ }
+
+}