am 55ffc99d: Make switch access work for incoming call screen

* commit '55ffc99d32b3c52494a5840116a5d12cbcef679c':
  Make switch access work for incoming call screen
diff --git a/InCallUI/res/layout/call_card_fragment.xml b/InCallUI/res/layout/call_card_fragment.xml
index 537eb51..dabba76 100644
--- a/InCallUI/res/layout/call_card_fragment.xml
+++ b/InCallUI/res/layout/call_card_fragment.xml
@@ -74,7 +74,7 @@
             android:layout_gravity="center_vertical"
             android:gravity="top|center_horizontal"
             android:scaleType="centerCrop"
-            android:contentDescription="@string/contactPhoto"
+            android:importantForAccessibility="no"
             android:background="@android:color/white"
             android:src="@drawable/img_no_image_automirrored" />
 
diff --git a/InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java b/InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java
index 4bd27db..2320027 100644
--- a/InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java
+++ b/InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java
@@ -29,9 +29,14 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Vibrator;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.view.accessibility.AccessibilityEventCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.widget.ExploreByTouchHelper;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -39,11 +44,16 @@
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.accessibility.AccessibilityNodeProvider;
 
 import com.android.incallui.R;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This is a copy of com.android.internal.widget.multiwaveview.GlowPadView with minor changes
@@ -124,6 +134,9 @@
     private boolean mDragging;
     private int mNewTargetResources;
 
+    private AccessibilityNodeProvider mAccessibilityNodeProvider;
+    private GlowpadExploreByTouchHelper mExploreByTouchHelper;
+
     private class AnimationBundle extends ArrayList<Tweener> {
         private static final long serialVersionUID = 0xA84D78726F127468L;
         private boolean mSuspended;
@@ -274,6 +287,9 @@
         mPointCloud = new PointCloud(pointDrawable);
         mPointCloud.makePointCloud(mInnerRadius, mOuterRadius);
         mPointCloud.glowManager.setRadius(mGlowRadius);
+
+        mExploreByTouchHelper = new GlowpadExploreByTouchHelper(this);
+        ViewCompat.setAccessibilityDelegate(this, mExploreByTouchHelper);
     }
 
     private int getResourceId(TypedArray a, int id) {
@@ -1355,4 +1371,103 @@
         }
         return replaced;
     }
+
+    public class GlowpadExploreByTouchHelper extends ExploreByTouchHelper {
+
+        private Rect mBounds = new Rect();
+
+        public GlowpadExploreByTouchHelper(View forView) {
+            super(forView);
+        }
+
+        @Override
+        protected int getVirtualViewAt(float x, float y) {
+            if (mGrabbedState == OnTriggerListener.CENTER_HANDLE) {
+                for (int i = 0; i < mTargetDrawables.size(); i++) {
+                    final TargetDrawable target = mTargetDrawables.get(i);
+                    if (target.isEnabled() && target.getBounds().contains((int) x, (int) y)) {
+                        return i;
+                    }
+                }
+                return INVALID_ID;
+            } else {
+                return HOST_ID;
+            }
+        }
+
+        @Override
+        protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
+            if (mGrabbedState == OnTriggerListener.CENTER_HANDLE) {
+                // Add virtual views backwards so that accessibility services like switch
+                // access traverse them in the correct order
+                for (int i = mTargetDrawables.size() - 1; i >= 0; i--) {
+                    if (mTargetDrawables.get(i).isEnabled()) {
+                        virtualViewIds.add(i);
+                    }
+                }
+            }
+        }
+
+        @Override
+        protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
+            if (virtualViewId >= 0 && virtualViewId < mTargetDescriptions.size()) {
+                event.setContentDescription(mTargetDescriptions.get(virtualViewId));
+            }
+        }
+
+        @Override
+        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
+            if (host == GlowPadView.this && event.getEventType()
+                    == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
+                event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+            }
+            super.onInitializeAccessibilityEvent(host, event);
+        }
+
+        @Override
+        public void onPopulateNodeForHost(AccessibilityNodeInfoCompat node) {
+            if (mGrabbedState == OnTriggerListener.NO_HANDLE) {
+                node.setClickable(true);
+                node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
+            }
+            mBounds.set(0, 0, GlowPadView.this.getWidth(), GlowPadView.this.getHeight());
+            node.setBoundsInParent(mBounds);
+        }
+
+        @Override
+        public boolean performAccessibilityAction(View host, int action, Bundle args) {
+            if (mGrabbedState == OnTriggerListener.NO_HANDLE) {
+                // Simulate handle being grabbed to expose targets.
+                trySwitchToFirstTouchState(mWaveCenterX, mWaveCenterY);
+                invalidateRoot();
+                return true;
+            }
+            return super.performAccessibilityAction(host, action, args);
+        }
+
+        @Override
+        protected void onPopulateNodeForVirtualView(int virtualViewId,
+                AccessibilityNodeInfoCompat node) {
+            if (virtualViewId < mTargetDrawables.size()) {
+                final TargetDrawable target = mTargetDrawables.get(virtualViewId);
+                node.setBoundsInParent(target.getBounds());
+                node.setClickable(true);
+                node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
+                node.setContentDescription(getTargetDescription(virtualViewId));
+            }
+        }
+
+        @Override
+        protected boolean onPerformActionForVirtualView(int virtualViewId, int action,
+                Bundle arguments) {
+            if (action == AccessibilityNodeInfo.ACTION_CLICK) {
+                if (virtualViewId >= 0 && virtualViewId < mTargetDrawables.size()) {
+                    dispatchTriggerEvent(virtualViewId);
+                    return true;
+                }
+            }
+            return false;
+        }
+
+    }
 }
diff --git a/InCallUI/src/com/android/incallui/widget/multiwaveview/TargetDrawable.java b/InCallUI/src/com/android/incallui/widget/multiwaveview/TargetDrawable.java
index d83a28c..adc5324 100644
--- a/InCallUI/src/com/android/incallui/widget/multiwaveview/TargetDrawable.java
+++ b/InCallUI/src/com/android/incallui/widget/multiwaveview/TargetDrawable.java
@@ -19,6 +19,7 @@
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
 import android.util.Log;
@@ -46,6 +47,7 @@
     private boolean mEnabled = true;
     private final int mResourceId;
     private int mNumDrawables = 1;
+    private Rect mBounds;
 
     /**
      * This is changed from the framework version to pass in the number of drawables in the
@@ -214,6 +216,17 @@
         return mDrawable != null ? mDrawable.getIntrinsicHeight() : 0;
     }
 
+    public Rect getBounds() {
+        if (mBounds == null) {
+            mBounds = new Rect();
+        }
+        mBounds.set((int) (mTranslationX + mPositionX - getWidth() * 0.5),
+                (int) (mTranslationY + mPositionY - getHeight() * 0.5),
+                (int) (mTranslationX + mPositionX + getWidth() * 0.5),
+                (int) (mTranslationY + mPositionY + getHeight() * 0.5));
+        return mBounds;
+    }
+
     public void draw(Canvas canvas) {
         if (mDrawable == null || !mEnabled) {
             return;