aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2011-12-12 08:43:38 -0800
committerVladimir Chtchetkine <vchtchetkine@google.com>2011-12-12 08:43:38 -0800
commitb3ae32deffd0dbe11874109595a4167c72845f49 (patch)
treeffe5a3a4e1e098410e925845513b88227492ac86
parent148fb01deacb3296b14ce2c28d56eeec2e725937 (diff)
downloadsdk-b3ae32deffd0dbe11874109595a4167c72845f49.zip
sdk-b3ae32deffd0dbe11874109595a4167c72845f49.tar.gz
sdk-b3ae32deffd0dbe11874109595a4167c72845f49.tar.bz2
Implements an app that captures touch events and transfers them to emulator.
This application is intended to provide realistic multi-touch emulation. Change-Id: I7bc477d99eea811a349ecc640f32cb4167d3ce18
-rw-r--r--apps/SdkController/.gitignore2
-rw-r--r--apps/SdkController/SdkControllerMultitouch/AndroidManifest.xml43
-rw-r--r--apps/SdkController/SdkControllerMultitouch/project.properties12
-rw-r--r--apps/SdkController/SdkControllerMultitouch/res/drawable-hdpi/ic_launcher.pngbin0 -> 4147 bytes
-rw-r--r--apps/SdkController/SdkControllerMultitouch/res/drawable-ldpi/ic_launcher.pngbin0 -> 1723 bytes
-rw-r--r--apps/SdkController/SdkControllerMultitouch/res/drawable-mdpi/ic_launcher.pngbin0 -> 2574 bytes
-rw-r--r--apps/SdkController/SdkControllerMultitouch/res/layout/main.xml10
-rw-r--r--apps/SdkController/SdkControllerMultitouch/res/values/strings.xml5
-rw-r--r--apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java282
9 files changed, 354 insertions, 0 deletions
diff --git a/apps/SdkController/.gitignore b/apps/SdkController/.gitignore
index 0bbcb2f..1ea39a4 100644
--- a/apps/SdkController/.gitignore
+++ b/apps/SdkController/.gitignore
@@ -3,3 +3,5 @@
SdkControllerLib/bin/
SdkControllerSensor/bin/
SdkControllerSensor/gen/
+SdkControllerMultitouch/bin/
+SdkControllerMultitouch/gen/
diff --git a/apps/SdkController/SdkControllerMultitouch/AndroidManifest.xml b/apps/SdkController/SdkControllerMultitouch/AndroidManifest.xml
new file mode 100644
index 0000000..8159efc
--- /dev/null
+++ b/apps/SdkController/SdkControllerMultitouch/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tools.sdkcontroller.sdkcontrollermultitouch"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="7" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ <activity
+ android:label="@string/app_name"
+ android:configChanges="orientation|keyboardHidden|mcc|mnc|locale|touchscreen|keyboard|navigation|screenLayout|fontScale"
+ android:name=".SdkControllerMultitouchActivity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/apps/SdkController/SdkControllerMultitouch/project.properties b/apps/SdkController/SdkControllerMultitouch/project.properties
new file mode 100644
index 0000000..d3d8dc4
--- /dev/null
+++ b/apps/SdkController/SdkControllerMultitouch/project.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-7
+android.library.reference.1=../SdkControllerLib
diff --git a/apps/SdkController/SdkControllerMultitouch/res/drawable-hdpi/ic_launcher.png b/apps/SdkController/SdkControllerMultitouch/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/apps/SdkController/SdkControllerMultitouch/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/apps/SdkController/SdkControllerMultitouch/res/drawable-ldpi/ic_launcher.png b/apps/SdkController/SdkControllerMultitouch/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/apps/SdkController/SdkControllerMultitouch/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/apps/SdkController/SdkControllerMultitouch/res/drawable-mdpi/ic_launcher.png b/apps/SdkController/SdkControllerMultitouch/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/apps/SdkController/SdkControllerMultitouch/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/apps/SdkController/SdkControllerMultitouch/res/layout/main.xml b/apps/SdkController/SdkControllerMultitouch/res/layout/main.xml
new file mode 100644
index 0000000..1371302
--- /dev/null
+++ b/apps/SdkController/SdkControllerMultitouch/res/layout/main.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+ <ImageView android:id="@+id/imageView"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+ </ImageView>
+</FrameLayout> \ No newline at end of file
diff --git a/apps/SdkController/SdkControllerMultitouch/res/values/strings.xml b/apps/SdkController/SdkControllerMultitouch/res/values/strings.xml
new file mode 100644
index 0000000..3db1f19
--- /dev/null
+++ b/apps/SdkController/SdkControllerMultitouch/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">SDK Controller Multitouch</string>
+
+</resources> \ No newline at end of file
diff --git a/apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java b/apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java
new file mode 100644
index 0000000..810eb80
--- /dev/null
+++ b/apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.tools.sdkcontroller.sdkcontrollermultitouch;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+import com.android.tools.sdkcontroller.lib.Emulator;
+import com.android.tools.sdkcontroller.lib.Emulator.EmulatorConnectionType;
+import com.android.tools.sdkcontroller.lib.OnEmulatorListener;
+
+import java.io.IOException;
+
+/**
+ * Encapsulates an application that monitors multi-touch activities on a device,
+ * and reports them to an Android Emulator application running on the host
+ * machine. This application is used to provide a realistic multi-touch emulation
+ * in Android Emulator.
+ */
+public class SdkControllerMultitouchActivity extends Activity implements OnEmulatorListener {
+ /** Tag for logging messages. */
+ private static final String TAG = "SdkControllerMultitouch";
+
+ /** TCP over USB connection to the emulator. */
+ private Emulator mEmulator;
+ /** View for this application. */
+ private View mView;
+ /** Listener to touch events. */
+ private TouchListener mTouchListener;
+ /** Multiplier for an X coordinate of a pointer. */
+ private float mDx = 1;
+ /** Multiplier for a Y coordinate of a pointer. */
+ private float mDy = 1;
+
+ /**
+ * Implements OnTouchListener interface that receives touch screen events,
+ * and reports them to the emulator application.
+ */
+ class TouchListener implements OnTouchListener {
+ /**
+ * Touchscreen event handler.
+ */
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ StringBuilder sb = new StringBuilder();
+ final int action = event.getAction();
+ final int action_code = action & MotionEvent.ACTION_MASK;
+ final int action_pid_index = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
+
+ /*
+ * Build message for the emulator.
+ */
+
+ switch (action_code) {
+ case MotionEvent.ACTION_MOVE:
+ sb.append("action=move");
+ for (int n = 0; n < event.getPointerCount(); n++) {
+ constructEventMessage(sb, event, n);
+ }
+ break;
+ case MotionEvent.ACTION_DOWN:
+ sb.append("action=down");
+ constructEventMessage(sb, event, action_pid_index);
+ break;
+ case MotionEvent.ACTION_UP:
+ sb.append("action=up pid=").append(event.getPointerId(action_pid_index));
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ sb.append("action=pdown");
+ constructEventMessage(sb, event, action_pid_index);
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ sb.append("action=pup pid=").append(event.getPointerId(action_pid_index));
+ break;
+ default:
+ Logw("Unknown action type: " + action_code);
+ return true;
+ }
+
+ Logv(sb.toString());
+ mEmulator.sendNotification(sb.toString() + '\0');
+ return true;
+ }
+
+ /**
+ * Constructs touch event message to be send to emulator.
+ *<p/>
+ * @param sb String builder where to construct the message.
+ * @param event Event for which to construct the message.
+ * @param ptr_index Index of the motion pointer for which to construct
+ * the message.
+ */
+ private void constructEventMessage(StringBuilder sb, MotionEvent event, int ptr_index) {
+ sb.append(" pid=").append(event.getPointerId(ptr_index));
+ sb.append(" x=").append((int) (mDx * event.getX(ptr_index)));
+ sb.append(" y=").append((int) (mDy * event.getY(ptr_index)));
+ sb.append(" pressure=").append((int) event.getPressure(ptr_index));
+ }
+ } // TouchListener
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ // Instantiate emulator connector.
+ try {
+ mEmulator = new Emulator(Emulator.MULTITOUCH_PORT,
+ EmulatorConnectionType.SYNC_CONNECTION, this);
+ } catch (IOException e) {
+ Loge("Exception while creating server socket: " + e.getMessage());
+ finish();
+ }
+
+ // Create listener for touch events.
+ mView = findViewById(R.id.imageView);
+ mTouchListener = new TouchListener();
+ }
+
+ /***************************************************************************
+ * OnEmulatorListener implementation
+ **************************************************************************/
+
+ /**
+ * Called when emulator is connected. NOTE: This method is called from the
+ * I/O loop, so all communication with the emulator will be "on hold" until
+ * this method returns.
+ */
+ @Override
+ public void onEmulatorConnected() {
+ }
+
+ /**
+ * Called when emulator is disconnected.
+ */
+ @Override
+ public void onEmulatorDisconnected() {
+ // Stop listening on events, and let it cool for a sec...
+ onStopEvents();
+ try {
+ Thread.sleep(500);
+ } catch (Exception e) {
+ }
+
+ // Instantiate emulator connector for the next client.
+ try {
+ mEmulator = new Emulator(Emulator.MULTITOUCH_PORT,
+ EmulatorConnectionType.SYNC_CONNECTION, this);
+ } catch (IOException e) {
+ Loge("Exception while creating server socket: " + e.getMessage());
+ finish();
+ }
+ }
+
+ /**
+ * Called when a query is received from the emulator. NOTE: This method is
+ * called from the I/O loop.
+ *<p/>
+ * @param query Name of the query received from the emulator. The allowed
+ * queries are:
+ * - 'start' - Starts delivering touch screen events to the emulator.
+ * - 'stop' - Stops delivering touch screen events to the emulator.
+ * @param param Query parameters.
+ * @return Zero-terminated reply string. String must be formatted as such:
+ * "ok|ko[:reply data]"
+ */
+ @Override
+ public String onEmulatorQuery(String query, String param) {
+ if (query.contentEquals("start")) {
+ return onQueryStart(param);
+ } else if (query.contentEquals("stop")) {
+ return onQueryStop();
+ } else {
+ Loge("Unknown query " + query + "(" + param + ")");
+ return "ko:Unknown query\0";
+ }
+ }
+
+ /***************************************************************************
+ * Emulator query handlers
+ **************************************************************************/
+
+ /**
+ * Handles 'start' query.
+ *<p/>
+ * @return 'ok:<WidthxHeight> on success, or 'ko:<reason>' on failure. Width
+ * and height returned on success represent width and height of the
+ * application view.
+ */
+ private String onQueryStart(String param) {
+ // Lets see if query has parameters.
+ int sep = param.indexOf('x');
+ if (sep != -1) {
+ String dx = param.substring(0, sep);
+ String dy = param.substring(sep + 1);
+ int x = Integer.parseInt(dx);
+ int y = Integer.parseInt(dy);
+ mDy = (float) y / (float) mView.getHeight();
+ mDx = (float) x / (float) mView.getWidth();
+ Logv("Emulator: " + x + "x" + y +
+ " to screen: " + mView.getWidth() + "x" + mView.getHeight() + " ratio: " +
+ mDx + "x" + mDy);
+ }
+ onStartEvents();
+ return "ok:" + mView.getWidth() + "x" + mView.getHeight() + "\0";
+ }
+
+ /**
+ * Handles 'stop' query.
+ *<p/>
+ * @return 'ok'.
+ */
+ private String onQueryStop() {
+ onStopEvents();
+ return "ok\0";
+ }
+
+ /***************************************************************************
+ * Internals
+ **************************************************************************/
+
+ /**
+ * Registers touch screen event listener, and starts receiving touch screen
+ * events.
+ */
+ private void onStartEvents() {
+ mView.post(new Runnable() {
+ @Override
+ public void run() {
+ mView.setOnTouchListener(mTouchListener);
+ }
+ });
+ }
+
+ /**
+ * Unregisters touch screen event listener, and stops receiving touch screen
+ * events.
+ */
+ private void onStopEvents() {
+ mView.post(new Runnable() {
+ @Override
+ public void run() {
+ mView.setOnTouchListener(null);
+ }
+ });
+ }
+
+ /***************************************************************************
+ * Logging wrappers
+ **************************************************************************/
+
+ private void Loge(String log) {
+ Log.e(TAG, log);
+ }
+
+ private void Logw(String log) {
+ Log.w(TAG, log);
+ }
+
+ private void Logv(String log) {
+ Log.v(TAG, log);
+ }
+}