AOD: Use double tap coordinates to trigger Ambient Indication

Bug: 38386446
Test: Double tap on AOD, verify that it still works. On device that supports double tap coordinates, verify that double tapping on ambient music opens ambient music.
Change-Id: Ic75ba731a980c9598c85927e83d2032f01da4822
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 3e424d0..5aaa6c7 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -38,6 +38,8 @@
 
     void setAnimateWakeup(boolean animateWakeup);
 
+    void onDoubleTap(float x, float y);
+
     interface Callback {
         default void onNotificationHeadsUp() {}
         default void onPowerSaveChanged(boolean active) {}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 73f5222..23da716 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -81,17 +81,18 @@
                         mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
                         null /* setting */,
                         dozeParameters.getPulseOnSigMotion(),
-                        DozeLog.PULSE_REASON_SENSOR_SIGMOTION),
+                        DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */),
                 mPickupSensor = new TriggerSensor(
                         mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
                         Settings.Secure.DOZE_PULSE_ON_PICK_UP,
                         config.pulseOnPickupAvailable(),
-                        DozeLog.PULSE_REASON_SENSOR_PICKUP),
+                        DozeLog.PULSE_REASON_SENSOR_PICKUP, false /* touchCoords */),
                 new TriggerSensor(
                         findSensorWithType(config.doubleTapSensorType()),
                         Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
                         true /* configured */,
-                        DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
+                        DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP,
+                        dozeParameters.doubleTapReportsTouchCoordinates())
         };
 
         mProxSensor = new ProxSensor();
@@ -207,16 +208,19 @@
         final boolean mConfigured;
         final int mPulseReason;
         final String mSetting;
+        final boolean mReportsTouchCoordinates;
 
         private boolean mRequested;
         private boolean mRegistered;
         private boolean mDisabled;
 
-        public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason) {
+        public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
+                boolean reportsTouchCoordinates) {
             mSensor = sensor;
             mSetting = setting;
             mConfigured = configured;
             mPulseReason = pulseReason;
+            mReportsTouchCoordinates = reportsTouchCoordinates;
         }
 
         public void setListening(boolean listen) {
@@ -276,7 +280,13 @@
                 }
 
                 mRegistered = false;
-                mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck);
+                float screenX = -1;
+                float screenY = -1;
+                if (mReportsTouchCoordinates && event.values.length >= 2) {
+                    screenX = event.values[0];
+                    screenY = event.values[1];
+                }
+                mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck, screenX, screenY);
                 updateListener();  // reregister, this sensor only fires once
             }));
         }
@@ -309,7 +319,12 @@
          * Called when a sensor requests a pulse
          * @param pulseReason Requesting sensor, e.g. {@link DozeLog#PULSE_REASON_SENSOR_PICKUP}
          * @param sensorPerformedProxCheck true if the sensor already checked for FAR proximity.
+         * @param screenX the location on the screen where the sensor fired or -1
+         *                if the sensor doesn't support reporting screen locations.
+         * @param screenY the location on the screen where the sensor fired or -1
+         *                if the sensor doesn't support reporting screen locations.
          */
-        void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck);
+        void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck,
+                float screenX, float screenY);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 693a690..ae936db 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -98,12 +98,14 @@
         requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
     }
 
-    private void onSensor(int pulseReason, boolean sensorPerformedProxCheck) {
+    private void onSensor(int pulseReason, boolean sensorPerformedProxCheck,
+            float screenX, float screenY) {
         boolean isDoubleTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP;
         boolean isPickup = pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
 
         if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) {
             if (isDoubleTap) {
+                mDozeHost.onDoubleTap(screenX, screenY);
                 mMachine.wakeUp();
             } else {
                 mDozeHost.extendPulse();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index d7e7abe..6b7397b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -157,6 +157,10 @@
         return 2 * getPulseVisibleDuration();
     }
 
+    public boolean doubleTapReportsTouchCoordinates() {
+        return mContext.getResources().getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
+    }
+
 
     /**
      * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 7564c82..aaa6447 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -32,7 +32,6 @@
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
 
-import android.R.style;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.annotation.NonNull;
@@ -99,14 +98,11 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.SystemService;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
@@ -120,7 +116,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
-import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.IWindowManager;
 import android.view.KeyEvent;
@@ -5302,6 +5297,37 @@
             mAnimateWakeup = animateWakeup;
         }
 
+        @Override
+        public void onDoubleTap(float screenX, float screenY) {
+            if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null 
+                && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
+                mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2);
+                float viewX = screenX - mTmpInt2[0];
+                float viewY = screenY - mTmpInt2[1];
+                if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth()
+                        && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) {
+                    dispatchDoubleTap(viewX, viewY);
+                }
+            }
+        }
+
+        public void dispatchDoubleTap(float viewX, float viewY) {
+            dispatchTap(mAmbientIndicationContainer, viewX, viewY);
+            dispatchTap(mAmbientIndicationContainer, viewX, viewY);
+        }
+
+        private void dispatchTap(View view, float x, float y) {
+            long now = SystemClock.elapsedRealtime();
+            dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN);
+            dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP);
+        }
+
+        private void dispatchTouchEvent(View view, float x, float y, long now, int action) {
+            MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */);
+            view.dispatchTouchEvent(ev);
+            ev.recycle();
+        }
+
         private boolean shouldAnimateWakeup() {
             return mAnimateWakeup;
         }