Merge "New dev tools option for window manager pointer location."
diff --git a/apps/Development/Android.mk b/apps/Development/Android.mk
index 1cef548..fa929b6 100644
--- a/apps/Development/Android.mk
+++ b/apps/Development/Android.mk
@@ -3,6 +3,7 @@
 
 LOCAL_MODULE_TAGS := eng
 
+LOCAL_STATIC_JAVA_LIBRARIES := android-common
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files) \
diff --git a/apps/Development/res/layout/development_settings.xml b/apps/Development/res/layout/development_settings.xml
index 9c04f5d..16c2cdf 100644
--- a/apps/Development/res/layout/development_settings.xml
+++ b/apps/Development/res/layout/development_settings.xml
@@ -54,10 +54,16 @@
             android:layout_below="@id/wait_for_debugger"
             android:layout_alignParentLeft="true" />
 
+        <Spinner android:id="@+id/pointer_location"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/separator"
+            android:layout_alignParentLeft="true" />
+
         <CheckBox android:id="@+id/show_load"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_below="@id/separator"
+            android:layout_below="@id/pointer_location"
             android:layout_alignParentLeft="true"
             android:text="@string/development_settings_show_load_text" />
 
diff --git a/apps/Development/src/com/android/development/DevelopmentSettings.java b/apps/Development/src/com/android/development/DevelopmentSettings.java
index 9cb6fc6..c01ea59 100644
--- a/apps/Development/src/com/android/development/DevelopmentSettings.java
+++ b/apps/Development/src/com/android/development/DevelopmentSettings.java
@@ -52,6 +52,7 @@
     private Button mDebugAppButton;
     private CheckBox mWaitForDebuggerCB;
     private CheckBox mAlwaysFinishCB;
+    private Spinner mPointerLocationSpinner;
     private CheckBox mShowLoadCB;
     private CheckBox mShowCpuCB;
     private CheckBox mEnableGLCB;
@@ -68,6 +69,7 @@
     private String mDebugApp;
     private boolean mWaitForDebugger;
     private boolean mAlwaysFinish;
+    private int mPointerLocation;
     private int mProcessLimit;
     private boolean mShowSleep;
     private boolean mShowXmpp;
@@ -94,6 +96,16 @@
         mWaitForDebuggerCB.setOnClickListener(mWaitForDebuggerClicked);
         mAlwaysFinishCB = (CheckBox)findViewById(R.id.always_finish);
         mAlwaysFinishCB.setOnClickListener(mAlwaysFinishClicked);
+        mPointerLocationSpinner = (Spinner)findViewById(R.id.pointer_location);
+        mPointerLocationSpinner.setOnItemSelectedListener(mPointerLocationChanged);
+        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
+                this,
+                android.R.layout.simple_spinner_item,
+                new String[] {
+                        "No Pointer Location",
+                        "Pointer Location" });
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mPointerLocationSpinner.setAdapter(adapter);
         mShowLoadCB = (CheckBox)findViewById(R.id.show_load);
         mShowLoadCB.setOnClickListener(mShowLoadClicked);
         mShowCpuCB = (CheckBox)findViewById(R.id.show_cpu);
@@ -113,7 +125,7 @@
         mCompatibilityModeCB.setOnClickListener(mCompatibilityModeClicked);
         mMaxProcsSpinner = (Spinner)findViewById(R.id.max_procs);
         mMaxProcsSpinner.setOnItemSelectedListener(mMaxProcsChanged);
-        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
+        adapter = new ArrayAdapter<String>(
                 this,
                 android.R.layout.simple_spinner_item,
                 new String[] {
@@ -169,6 +181,7 @@
         super.onResume();
         updateDebugOptions();
         updateFinishOptions();
+        updatePointerLocationOptions();
         updateProcessLimitOptions();
         updateSharedOptions();
         updateFlingerOptions();
@@ -221,6 +234,17 @@
         mAlwaysFinishCB.setChecked(mAlwaysFinish);
     }
 
+    private void writePointerLocationOptions() {
+        Settings.System.putInt(getContentResolver(),
+                Settings.System.POINTER_LOCATION, mPointerLocation);
+    }
+
+    private void updatePointerLocationOptions() {
+        mPointerLocation = Settings.System.getInt(getContentResolver(),
+                Settings.System.POINTER_LOCATION, 0);
+        mPointerLocationSpinner.setSelection(mPointerLocation);
+    }
+
     private void writeProcessLimitOptions() {
         try {
             ActivityManagerNative.getDefault().setProcessLimit(mProcessLimit);
@@ -420,6 +444,18 @@
         }
     };
 
+    private Spinner.OnItemSelectedListener mPointerLocationChanged
+                                    = new Spinner.OnItemSelectedListener() {
+        public void onItemSelected(android.widget.AdapterView av, View v,
+                                    int position, long id) {
+            mPointerLocation = position;
+            writePointerLocationOptions();
+        }
+
+        public void onNothingSelected(android.widget.AdapterView av) {
+        }
+    };
+
     private Spinner.OnItemSelectedListener mMaxProcsChanged
                                     = new Spinner.OnItemSelectedListener() {
         public void onItemSelected(android.widget.AdapterView av, View v,
diff --git a/apps/Development/src/com/android/development/PointerLocation.java b/apps/Development/src/com/android/development/PointerLocation.java
index 38b4af2..88828b0 100644
--- a/apps/Development/src/com/android/development/PointerLocation.java
+++ b/apps/Development/src/com/android/development/PointerLocation.java
@@ -16,20 +16,11 @@
 
 package com.android.development;
 
-import android.app.Activity;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.FontMetricsInt;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-import android.view.WindowManager;
-import android.view.VelocityTracker;
-import android.view.View;
+import com.android.common.ui.PointerLocationView;
 
-import java.util.ArrayList;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
 
 /**
  * Demonstrates wrapping a layout in a ScrollView.
@@ -39,304 +30,11 @@
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        setContentView(new MyView(this));
+        setContentView(new PointerLocationView(this));
         
         // Make the screen full bright for this activity.
         WindowManager.LayoutParams lp = getWindow().getAttributes();
         lp.screenBrightness = 1.0f;
         getWindow().setAttributes(lp);
     }
-    
-    public static class PointerState {
-        private final ArrayList<Float> mXs = new ArrayList<Float>();
-        private final ArrayList<Float> mYs = new ArrayList<Float>();
-        private boolean mCurDown;
-        private int mCurX;
-        private int mCurY;
-        private float mCurPressure;
-        private float mCurSize;
-        private int mCurWidth;
-        private VelocityTracker mVelocity;
-    }
-    
-    public class MyView extends View {
-        private final ViewConfiguration mVC;
-        private final Paint mTextPaint;
-        private final Paint mTextBackgroundPaint;
-        private final Paint mTextLevelPaint;
-        private final Paint mPaint;
-        private final Paint mTargetPaint;
-        private final Paint mPathPaint;
-        private final FontMetricsInt mTextMetrics = new FontMetricsInt();
-        private int mHeaderBottom;
-        private boolean mCurDown;
-        private int mCurNumPointers;
-        private int mMaxNumPointers;
-        private final ArrayList<PointerState> mPointers
-                 = new ArrayList<PointerState>();
-        
-        public MyView(Context c) {
-            super(c);
-            mVC = ViewConfiguration.get(c);
-            mTextPaint = new Paint();
-            mTextPaint.setAntiAlias(true);
-            mTextPaint.setTextSize(10
-                    * getResources().getDisplayMetrics().density);
-            mTextPaint.setARGB(255, 0, 0, 0);
-            mTextBackgroundPaint = new Paint();
-            mTextBackgroundPaint.setAntiAlias(false);
-            mTextBackgroundPaint.setARGB(128, 255, 255, 255);
-            mTextLevelPaint = new Paint();
-            mTextLevelPaint.setAntiAlias(false);
-            mTextLevelPaint.setARGB(192, 255, 0, 0);
-            mPaint = new Paint();
-            mPaint.setAntiAlias(true);
-            mPaint.setARGB(255, 255, 255, 255);
-            mPaint.setStyle(Paint.Style.STROKE);
-            mPaint.setStrokeWidth(2);
-            mTargetPaint = new Paint();
-            mTargetPaint.setAntiAlias(false);
-            mTargetPaint.setARGB(255, 0, 0, 192);
-            mPathPaint = new Paint();
-            mPathPaint.setAntiAlias(false);
-            mPathPaint.setARGB(255, 0, 96, 255);
-            mPaint.setStyle(Paint.Style.STROKE);
-            mPaint.setStrokeWidth(1);
-            
-            PointerState ps = new PointerState();
-            ps.mVelocity = VelocityTracker.obtain();
-            mPointers.add(ps);
-        }
-
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-            mTextPaint.getFontMetricsInt(mTextMetrics);
-            mHeaderBottom = -mTextMetrics.ascent+mTextMetrics.descent+2;
-            Log.i("foo", "Metrics: ascent=" + mTextMetrics.ascent
-                    + " descent=" + mTextMetrics.descent
-                    + " leading=" + mTextMetrics.leading
-                    + " top=" + mTextMetrics.top
-                    + " bottom=" + mTextMetrics.bottom);
-        }
-
-        @Override
-        protected void onDraw(Canvas canvas) {
-            final int w = getWidth();
-            final int itemW = w/7;
-            final int base = -mTextMetrics.ascent+1;
-            final int bottom = mHeaderBottom;
-            
-            final int NP = mPointers.size();
-            
-            if (NP > 0) {
-                final PointerState ps = mPointers.get(0);
-                canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint);
-                canvas.drawText("P: " + mCurNumPointers + " / " + mMaxNumPointers,
-                        1, base, mTextPaint);
-                
-                final int N = ps.mXs.size();
-                if ((mCurDown && ps.mCurDown) || N == 0) {
-                    canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint);
-                    canvas.drawText("X: " + ps.mCurX, 1 + itemW, base, mTextPaint);
-                    canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint);
-                    canvas.drawText("Y: " + ps.mCurY, 1 + itemW * 2, base, mTextPaint);
-                } else {
-                    float dx = ps.mXs.get(N-1) - ps.mXs.get(0);
-                    float dy = ps.mYs.get(N-1) - ps.mYs.get(0);
-                    canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom,
-                            Math.abs(dx) < mVC.getScaledTouchSlop()
-                            ? mTextBackgroundPaint : mTextLevelPaint);
-                    canvas.drawText("dX: " + String.format("%.1f", dx), 1 + itemW, base, mTextPaint);
-                    canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom,
-                            Math.abs(dy) < mVC.getScaledTouchSlop()
-                            ? mTextBackgroundPaint : mTextLevelPaint);
-                    canvas.drawText("dY: " + String.format("%.1f", dy), 1 + itemW * 2, base, mTextPaint);
-                }
-                
-                canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint);
-                int velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getXVelocity() * 1000);
-                canvas.drawText("Xv: " + velocity, 1 + itemW * 3, base, mTextPaint);
-                
-                canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint);
-                velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getYVelocity() * 1000);
-                canvas.drawText("Yv: " + velocity, 1 + itemW * 4, base, mTextPaint);
-                
-                canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint);
-                canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCurPressure * itemW) - 1,
-                        bottom, mTextLevelPaint);
-                canvas.drawText("Prs: " + String.format("%.2f", ps.mCurPressure), 1 + itemW * 5,
-                        base, mTextPaint);
-                
-                canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint);
-                canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCurSize * itemW) - 1,
-                        bottom, mTextLevelPaint);
-                canvas.drawText("Size: " + String.format("%.2f", ps.mCurSize), 1 + itemW * 6,
-                        base, mTextPaint);
-            }
-            
-            for (int p=0; p<NP; p++) {
-                final PointerState ps = mPointers.get(p);
-                
-                if (mCurDown && ps.mCurDown) {
-                    canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint);
-                    canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint);
-                    int pressureLevel = (int)(ps.mCurPressure*255);
-                    mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel);
-                    canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint);
-                    canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint);
-                }
-            }
-            
-            for (int p=0; p<NP; p++) {
-                final PointerState ps = mPointers.get(p);
-                
-                final int N = ps.mXs.size();
-                float lastX=0, lastY=0;
-                boolean haveLast = false;
-                boolean drawn = false;
-                mPaint.setARGB(255, 128, 255, 255);
-                for (int i=0; i<N; i++) {
-                    float x = ps.mXs.get(i);
-                    float y = ps.mYs.get(i);
-                    if (Float.isNaN(x)) {
-                        haveLast = false;
-                        continue;
-                    }
-                    if (haveLast) {
-                        canvas.drawLine(lastX, lastY, x, y, mPathPaint);
-                        canvas.drawPoint(lastX, lastY, mPaint);
-                        drawn = true;
-                    }
-                    lastX = x;
-                    lastY = y;
-                    haveLast = true;
-                }
-                
-                if (drawn) {
-                    if (ps.mVelocity != null) {
-                        mPaint.setARGB(255, 255, 64, 128);
-                        float xVel = ps.mVelocity.getXVelocity() * (1000/60);
-                        float yVel = ps.mVelocity.getYVelocity() * (1000/60);
-                        canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint);
-                    } else {
-                        canvas.drawPoint(lastX, lastY, mPaint);
-                    }
-                }
-            }
-        }
-
-        @Override
-        public boolean onTouchEvent(MotionEvent event) {
-            int action = event.getAction();
-            
-            //Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action)
-            //        + " pointers=" + event.getPointerCount());
-            
-            int NP = mPointers.size();
-            
-            //mRect.set(0, 0, getWidth(), mHeaderBottom+1);
-            //invalidate(mRect);
-            //if (mCurDown) {
-            //    mRect.set(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
-            //            mCurX+mCurWidth+3, mCurY+mCurWidth+3);
-            //} else {
-            //    mRect.setEmpty();
-            //}
-            if (action == MotionEvent.ACTION_DOWN) {
-                for (int p=0; p<NP; p++) {
-                    final PointerState ps = mPointers.get(p);
-                    ps.mXs.clear();
-                    ps.mYs.clear();
-                    ps.mVelocity = VelocityTracker.obtain();
-                    ps.mCurDown = false;
-                }
-                mPointers.get(0).mCurDown = true;
-                mMaxNumPointers = 0;
-                Log.i("Pointer", "Pointer 1: DOWN");
-            }
-            
-            if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
-                final int id = (action&MotionEvent.ACTION_POINTER_ID_MASK)
-                        >> MotionEvent.ACTION_POINTER_ID_SHIFT;
-                while (NP <= id) {
-                    PointerState ps = new PointerState();
-                    ps.mVelocity = VelocityTracker.obtain();
-                    mPointers.add(ps);
-                    NP++;
-                }
-                final PointerState ps = mPointers.get(id);
-                ps.mVelocity = VelocityTracker.obtain();
-                ps.mCurDown = true;
-                Log.i("Pointer", "Pointer " + (id+1) + ": DOWN");
-            }
-            
-            final int NI = event.getPointerCount();
-            
-            mCurDown = action != MotionEvent.ACTION_UP
-                    && action != MotionEvent.ACTION_CANCEL;
-            mCurNumPointers = mCurDown ? NI : 0;
-            if (mMaxNumPointers < mCurNumPointers) {
-                mMaxNumPointers = mCurNumPointers;
-            }
-            
-            for (int i=0; i<NI; i++) {
-                final PointerState ps = mPointers.get(event.getPointerId(i));
-                ps.mVelocity.addMovement(event);
-                ps.mVelocity.computeCurrentVelocity(1);
-                final int N = event.getHistorySize();
-                for (int j=0; j<N; j++) {
-                    Log.i("Pointer", "Pointer " + (i+1) + ": ("
-                            + event.getHistoricalX(i, j)
-                            + ", " + event.getHistoricalY(i, j) + ")"
-                            + " Prs=" + event.getHistoricalPressure(i, j)
-                            + " Size=" + event.getHistoricalSize(i, j));
-                    ps.mXs.add(event.getHistoricalX(i, j));
-                    ps.mYs.add(event.getHistoricalY(i, j));
-                }
-                Log.i("Pointer", "Pointer " + (i+1) + ": ("
-                        + event.getX(i) + ", " + event.getY(i) + ")"
-                        + " Prs=" + event.getPressure(i)
-                        + " Size=" + event.getSize(i));
-                ps.mXs.add(event.getX(i));
-                ps.mYs.add(event.getY(i));
-                ps.mCurX = (int)event.getX(i);
-                ps.mCurY = (int)event.getY(i);
-                //Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX
-                //        + "," + ps.mCurY + ")");
-                ps.mCurPressure = event.getPressure(i);
-                ps.mCurSize = event.getSize(i);
-                ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3));
-            }
-            
-            if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) {
-                final int id = (action&MotionEvent.ACTION_POINTER_ID_MASK)
-                        >> MotionEvent.ACTION_POINTER_ID_SHIFT;
-                final PointerState ps = mPointers.get(id);
-                ps.mXs.add(Float.NaN);
-                ps.mYs.add(Float.NaN);
-                ps.mCurDown = false;
-                Log.i("Pointer", "Pointer " + (id+1) + ": UP");
-            }
-            
-            if (action == MotionEvent.ACTION_UP) {
-                for (int i=0; i<NI; i++) {
-                    final PointerState ps = mPointers.get(event.getPointerId(i));
-                    if (ps.mCurDown) {
-                        ps.mCurDown = false;
-                        Log.i("Pointer", "Pointer " + (i+1) + ": UP");
-                    }
-                }
-            }
-            
-            //if (mCurDown) {
-            //    mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
-            //            mCurX+mCurWidth+3, mCurY+mCurWidth+3);
-            //}
-            //invalidate(mRect);
-            invalidate();
-            return true;
-        }
-        
-    }
 }