aboutsummaryrefslogtreecommitdiffstats
path: root/apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java')
-rw-r--r--apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java210
1 files changed, 165 insertions, 45 deletions
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
index 810eb80..ce4ac1d 100644
--- a/apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java
+++ b/apps/SdkController/SdkControllerMultitouch/src/com/android/tools/sdkcontroller/sdkcontrollermultitouch/SdkControllerMultitouchActivity.java
@@ -16,39 +16,52 @@
package com.android.tools.sdkcontroller.sdkcontrollermultitouch;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
import android.app.Activity;
+import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
+import android.view.WindowManager;
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.
+ * 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";
+ /** Received frame is JPEG image. */
+ private static final int FRAME_JPEG = 1;
+ /** Received frame is RGB565 bitmap. */
+ private static final int FRAME_RGB565 = 2;
+ /** Received frame is RGB888 bitmap. */
+ private static final int FRAME_RGB888 = 3;
/** TCP over USB connection to the emulator. */
private Emulator mEmulator;
/** View for this application. */
- private View mView;
+ private MultiTouchView 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;
+ /** Width of the emulator's display. */
+ private int mEmulatorWidth = 0;
+ /** Height of the emulator's display. */
+ private int mEmulatorHeight = 0;
+ /** Bitmap storage. */
+ private int[] mColors;
/**
* Implements OnTouchListener interface that receives touch screen events,
@@ -56,7 +69,7 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
*/
class TouchListener implements OnTouchListener {
/**
- * Touchscreen event handler.
+ * Touch screen event handler.
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
@@ -73,19 +86,19 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
case MotionEvent.ACTION_MOVE:
sb.append("action=move");
for (int n = 0; n < event.getPointerCount(); n++) {
- constructEventMessage(sb, event, n);
+ mView.constructEventMessage(sb, event, n);
}
break;
case MotionEvent.ACTION_DOWN:
sb.append("action=down");
- constructEventMessage(sb, event, action_pid_index);
+ mView.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);
+ mView.constructEventMessage(sb, event, action_pid_index);
break;
case MotionEvent.ACTION_POINTER_UP:
sb.append("action=pup pid=").append(event.getPointerId(action_pid_index));
@@ -99,21 +112,6 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
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. */
@@ -121,6 +119,8 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
+ mView = (MultiTouchView) findViewById(R.id.imageView);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Instantiate emulator connector.
try {
@@ -132,10 +132,39 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
}
// Create listener for touch events.
- mView = findViewById(R.id.imageView);
mTouchListener = new TouchListener();
}
+ /**
+ * Updates application's screen accordingly to the emulator screen.
+ *
+ * @param e_width Width of the emulator screen.
+ * @param e_height Height of the emulator screen.
+ */
+ private void updateDisplay(int e_width, int e_height) {
+ if (e_width != mEmulatorWidth || e_height != mEmulatorHeight) {
+ mEmulatorWidth = e_width;
+ mEmulatorHeight = e_height;
+
+ boolean rotateDisplay = false;
+ int w = mView.getWidth();
+ int h = mView.getHeight();
+ if (w > h != e_width > e_height) {
+ rotateDisplay = true;
+ int tmp = w;
+ w = h;
+ h = tmp;
+ }
+
+ float dx = (float) w / (float) e_width;
+ float dy = (float) h / (float) e_height;
+ mView.setDxDy(dx, dy, rotateDisplay);
+ Logv("Dispay updated: " + e_width + " x " + e_height +
+ " -> " + w + " x " + h + " ratio: " +
+ dx + " x " + dy);
+ }
+ }
+
/***************************************************************************
* OnEmulatorListener implementation
**************************************************************************/
@@ -147,6 +176,7 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
*/
@Override
public void onEmulatorConnected() {
+ Logv("Emulator is connected");
}
/**
@@ -154,6 +184,7 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
*/
@Override
public void onEmulatorDisconnected() {
+ Logv("Emulator is disconnected.");
// Stop listening on events, and let it cool for a sec...
onStopEvents();
try {
@@ -166,7 +197,7 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
mEmulator = new Emulator(Emulator.MULTITOUCH_PORT,
EmulatorConnectionType.SYNC_CONNECTION, this);
} catch (IOException e) {
- Loge("Exception while creating server socket: " + e.getMessage());
+ Loge("Exception while recreating server socket: " + e.getMessage());
finish();
}
}
@@ -174,11 +205,11 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
/**
* 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.
+ * 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]"
@@ -195,13 +226,105 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
}
}
+ /**
+ * Called when a BLOB query is received from the emulator.
+ * <p/>
+ * This query is used to deliver framebuffer updates in the emulator. The
+ * blob contains an update header, followed by the bitmap containing updated
+ * rectangle. The header is defined as MTFrameHeader structure in
+ * external/qemu/android/multitouch-port.h
+ * <p/>
+ * NOTE: This method is called from the I/O loop, so all communication with
+ * the emulator will be "on hold" until this method returns.
+ *
+ * @param array contains BLOB data for the query.
+ * @return Empty string: this query doesn't require any response.
+ */
+ @Override
+ public String onEmulatorBlobQuery(byte[] array) {
+ final ByteBuffer bb = ByteBuffer.wrap(array);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+
+ // Read frame header.
+ final int header_size = bb.getInt();
+ final int disp_width = bb.getInt();
+ final int disp_height = bb.getInt();
+ final int x = bb.getInt();
+ final int y = bb.getInt();
+ final int w = bb.getInt();
+ final int h = bb.getInt();
+ final int bpl = bb.getInt();
+ final int bpp = bb.getInt();
+ final int format = bb.getInt();
+
+ // Update application display.
+ updateDisplay(disp_width, disp_height);
+
+ mView.post(new Runnable() {
+ @Override
+ public void run() {
+ if (format == FRAME_JPEG) {
+ /*
+ * Framebuffer is in JPEG format.
+ */
+
+ final ByteArrayInputStream jpg = new ByteArrayInputStream(bb.array());
+ // Advance input stream to JPEG image.
+ jpg.skip(header_size);
+ // Draw the image.
+ mView.drawJpeg(x, y, w, h, jpg);
+ } else {
+ /*
+ * Framebuffer is in a raw RGB format.
+ */
+
+ final int pixel_num = h * w;
+ // Advance stream to the beginning of framebuffer data.
+ bb.position(header_size);
+
+ // Make sure that mColors is large enough to contain the
+ // update bitmap.
+ if (mColors == null || mColors.length < pixel_num) {
+ mColors = new int[pixel_num];
+ }
+
+ // Convert the blob bitmap into bitmap that we will display.
+ if (format == FRAME_RGB565) {
+ for (int n = 0; n < pixel_num; n++) {
+ // Blob bitmap is in RGB565 format.
+ final int color = bb.getShort();
+ final int r = ((color & 0xf800) >> 8) | ((color & 0xf800) >> 14);
+ final int g = ((color & 0x7e0) >> 3) | ((color & 0x7e0) >> 9);
+ final int b = ((color & 0x1f) << 3) | ((color & 0x1f) >> 2);
+ mColors[n] = Color.rgb(r, g, b);
+ }
+ } else if (format == FRAME_RGB888) {
+ for (int n = 0; n < pixel_num; n++) {
+ // Blob bitmap is in RGB565 format.
+ final int r = bb.getChar();
+ final int g = bb.getChar();
+ final int b = bb.getChar();
+ mColors[n] = Color.rgb(r, g, b);
+ }
+ } else {
+ Logw("Invalid framebuffer format: " + format);
+ return;
+ }
+ mView.drawBitmap(x, y, w, h, mColors);
+ }
+ }
+ });
+
+ return "";
+ }
+
/***************************************************************************
* 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.
@@ -210,15 +333,12 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
// 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);
+ final String dx = param.substring(0, sep);
+ final String dy = param.substring(sep + 1);
+ final int x = Integer.parseInt(dx);
+ final int y = Integer.parseInt(dy);
+
+ updateDisplay(x, y);
}
onStartEvents();
return "ok:" + mView.getWidth() + "x" + mView.getHeight() + "\0";
@@ -226,7 +346,7 @@ public class SdkControllerMultitouchActivity extends Activity implements OnEmula
/**
* Handles 'stop' query.
- *<p/>
+ *
* @return 'ok'.
*/
private String onQueryStop() {