Add support dual display support doze tap gesture

Test: manual, atest DozeSensorsTest
Bug: 192805135
Change-Id: I08a98bf16753631afd31cb750c541c7443df1b9e
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index a1f7aa1..f2c294a 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -22,6 +22,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.internal.R;
 
@@ -32,7 +33,7 @@
  */
 @TestApi
 public class AmbientDisplayConfiguration {
-
+    private static final String TAG = "AmbientDisplayConfig";
     private final Context mContext;
     private final boolean mAlwaysOnByDefault;
 
@@ -141,11 +142,20 @@
     }
 
     /** {@hide} */
-    public String tapSensorType() {
+    private String tapSensorType() {
         return mContext.getResources().getString(R.string.config_dozeTapSensorType);
     }
 
     /** {@hide} */
+    public String tapSensorType(int posture) {
+        return getSensorTypeForPosture(
+                mContext.getResources().getStringArray(R.array.config_dozeTapSensorPostureMapping),
+                tapSensorType(),
+                posture
+        );
+    }
+
+    /** {@hide} */
     public String longPressSensorType() {
         return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
     }
@@ -241,4 +251,18 @@
     private boolean boolSetting(String name, int user, int def) {
         return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, def, user) != 0;
     }
+
+    private String getSensorTypeForPosture(
+            String[] postureMapping,
+            String defaultSensorType,
+            int posture) {
+        String sensorType = defaultSensorType;
+        if (posture < postureMapping.length) {
+            sensorType = postureMapping[posture];
+        } else {
+            Log.e(TAG, "Unsupported doze posture " + posture);
+        }
+
+        return TextUtils.isEmpty(sensorType) ? defaultSensorType : sensorType;
+    }
 }
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 689d75b..4596e96 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2323,6 +2323,15 @@
     <!-- Type of the tap sensor. Empty if tap is not supported. -->
     <string name="config_dozeTapSensorType" translatable="false"></string>
 
+    <!-- Type of the ambient tap sensor per device posture (defined by WM Jetpack posture).
+         Unspecified values use config_dozeTapSensor -->
+    <string-array name="config_dozeTapSensorPostureMapping" translatable="false">
+        <item></item> <!-- UNKNOWN -->
+        <item></item> <!-- CLOSED -->
+        <item></item> <!-- HALF_OPENED -->
+        <item></item> <!-- OPENED -->
+    </string-array>
+
     <!-- Type of the long press sensor. Empty if long press is not supported. -->
     <string name="config_dozeLongPressSensorType" translatable="false"></string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4e8d915..7af6b71 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3255,6 +3255,7 @@
 
   <java-symbol type="string" name="config_dozeDoubleTapSensorType" />
   <java-symbol type="string" name="config_dozeTapSensorType" />
+  <java-symbol type="array" name="config_dozeTapSensorPostureMapping" />
   <java-symbol type="bool" name="config_dozePulsePickup" />
 
   <!-- Used for MimeIconUtils. -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 5e495f0..fd2b0e0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -191,6 +191,15 @@
      low powered state yet. -->
     <bool name="doze_single_tap_uses_prox">true</bool>
 
+    <!-- Doze: whether the single tap sensor uses the proximity sensor in the given posture.
+        See doze_single_tap_uses_prox for usage. -->
+    <integer-array name="doze_single_tap_uses_prox_posture_mapping">
+        <item>1</item> <!-- UNKNOWN -->
+        <item>1</item> <!-- CLOSED -->
+        <item>1</item> <!-- HALF_OPENED -->
+        <item>1</item> <!-- OPENED -->
+    </integer-array>
+
     <!-- Doze: whether the long press sensor uses the proximity sensor.
      If both this parameter and doze_selectively_register_prox are true, registration for the
      sensor will be delayed when the device first enters dozing but the device has not entered its
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 55e6154..099252b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -47,6 +47,7 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.plugins.SensorManagerPlugin;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.sensors.AsyncSensorManager;
 import com.android.systemui.util.sensors.ProximitySensor;
 import com.android.systemui.util.settings.SecureSettings;
@@ -82,6 +83,9 @@
     private boolean mListeningTouchScreenSensors;
     private boolean mListeningProxSensors;
 
+    @DevicePostureController.DevicePostureInt
+    private int mDevicePosture;
+
     // whether to only register sensors that use prox when the display state is dozing or off
     private boolean mSelectivelyRegisterProxSensors;
 
@@ -106,7 +110,8 @@
             DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
             Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog,
             ProximitySensor proximitySensor, SecureSettings secureSettings,
-            AuthController authController) {
+            AuthController authController,
+            int devicePosture) {
         mContext = context;
         mSensorManager = sensorManager;
         mConfig = config;
@@ -120,6 +125,7 @@
         mListeningProxSensors = !mSelectivelyRegisterProxSensors;
         mScreenOffUdfpsEnabled =
                 config.screenOffUdfpsEnabled(KeyguardUpdateMonitor.getCurrentUser());
+        mDevicePosture = devicePosture;
 
         boolean udfpsEnrolled =
                 authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser());
@@ -150,7 +156,7 @@
                         true /* touchscreen */,
                         dozeLog),
                 new TriggerSensor(
-                        findSensorWithType(config.tapSensorType()),
+                        findSensorWithType(config.tapSensorType(mDevicePosture)),
                         Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
                         true /* settingDef */,
                         true /* configured */,
@@ -158,7 +164,7 @@
                         false /* reports touch coordinates */,
                         true /* touchscreen */,
                         false /* ignoresSetting */,
-                        dozeParameters.singleTapUsesProx() /* requiresProx */,
+                        dozeParameters.singleTapUsesProx(mDevicePosture) /* requiresProx */,
                         dozeLog),
                 new TriggerSensor(
                         findSensorWithType(config.longPressSensorType()),
@@ -370,6 +376,8 @@
     /** Dump current state */
     public void dump(PrintWriter pw) {
         pw.println("mListening=" + mListening);
+        pw.println("mDevicePosture="
+                + DevicePostureController.devicePostureToString(mDevicePosture));
         pw.println("mListeningTouchScreenSensors=" + mListeningTouchScreenSensors);
         pw.println("mSelectivelyRegisterProxSensors=" + mSelectivelyRegisterProxSensors);
         pw.println("mListeningProxSensors=" + mListeningProxSensors);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 756adca..1e7f0d9 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -41,6 +41,7 @@
 import com.android.systemui.doze.DozeMachine.State;
 import com.android.systemui.doze.dagger.DozeScope;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -95,6 +96,9 @@
     private final DelayableExecutor mMainExecutor;
     private final KeyguardStateController mKeyguardStateController;
     private final UiEventLogger mUiEventLogger;
+    private final DevicePostureController mDevicePostureController;
+
+    private @DevicePostureController.DevicePostureInt int mDevicePosture;
 
     private long mNotificationPulseTime;
     private boolean mPulsePending;
@@ -182,7 +186,8 @@
             SecureSettings secureSettings, AuthController authController,
             @Main DelayableExecutor mainExecutor,
             UiEventLogger uiEventLogger,
-            KeyguardStateController keyguardStateController) {
+            KeyguardStateController keyguardStateController,
+            DevicePostureController devicePostureController) {
         mContext = context;
         mDozeHost = dozeHost;
         mConfig = config;
@@ -190,9 +195,11 @@
         mSensorManager = sensorManager;
         mWakeLock = wakeLock;
         mAllowPulseTriggers = true;
+        mDevicePostureController = devicePostureController;
+        mDevicePosture = devicePostureController.getDevicePosture();
         mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters,
                 config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor,
-                secureSettings, authController);
+                secureSettings, authController, mDevicePosture);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
         mDockManager = dockManager;
         mProxCheck = proxCheck;
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 a8c62fe..611f273 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -22,6 +22,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.Log;
 import android.util.MathUtils;
 
 import androidx.annotation.NonNull;
@@ -35,6 +36,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.tuner.TunerService;
 
 import java.io.FileDescriptor;
@@ -256,9 +258,20 @@
     }
 
     /**
+     * Whether the single tap sensor uses the proximity sensor for this device posture.
+     */
+    public boolean singleTapUsesProx(@DevicePostureController.DevicePostureInt int devicePosture) {
+        return getPostureSpecificBool(
+                mResources.getIntArray(R.array.doze_single_tap_uses_prox_posture_mapping),
+                singleTapUsesProx(),
+                devicePosture
+        );
+    }
+
+    /**
      * Whether the single tap sensor uses the proximity sensor.
      */
-    public boolean singleTapUsesProx() {
+    private boolean singleTapUsesProx() {
         return mResources.getBoolean(R.bool.doze_single_tap_uses_prox);
     }
 
@@ -308,6 +321,20 @@
         pw.println(getSelectivelyRegisterSensorsUsingProx());
     }
 
+    private boolean getPostureSpecificBool(
+            int[] postureMapping,
+            boolean defaultSensorBool,
+            int posture) {
+        boolean bool = defaultSensorBool;
+        if (posture < postureMapping.length) {
+            bool = postureMapping[posture] != 0;
+        } else {
+            Log.e("DozeParameters", "Unsupported doze posture " + posture);
+        }
+
+        return bool;
+    }
+
     interface Callback {
         /**
          * Invoked when the value of getAlwaysOn may have changed.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java
index fbfa5e5..8596875 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java
@@ -50,6 +50,26 @@
     /** Return the current device posture. */
     @DevicePostureInt int getDevicePosture();
 
+    /**
+     * String representation of DevicePostureInt.
+     */
+    static String devicePostureToString(@DevicePostureInt int posture) {
+        switch (posture) {
+            case DEVICE_POSTURE_CLOSED:
+                return "DEVICE_POSTURE_CLOSED";
+            case DEVICE_POSTURE_HALF_OPENED:
+                return "DEVICE_POSTURE_HALF_OPENED";
+            case DEVICE_POSTURE_OPENED:
+                return "DEVICE_POSTURE_OPENED";
+            case DEVICE_POSTURE_FLIPPED:
+                return "DEVICE_POSTURE_FLIPPED";
+            case DEVICE_POSTURE_UNKNOWN:
+                return "DEVICE_POSTURE_UNKNOWN";
+            default:
+                return "UNSUPPORTED POSTURE posture=" + posture;
+        }
+    }
+
     /** Callback to be notified about device posture changes. */
     interface Callback {
         /** Called when the posture changes. */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index d6226aa..866791c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -40,7 +40,7 @@
         when(params.doubleTapReportsTouchCoordinates()).thenReturn(false);
         when(params.getDisplayNeedsBlanking()).thenReturn(false);
         when(params.getSelectivelyRegisterSensorsUsingProx()).thenReturn(false);
-        when(params.singleTapUsesProx()).thenReturn(true);
+        when(params.singleTapUsesProx(anyInt())).thenReturn(true);
         when(params.longPressUsesProx()).thenReturn(true);
         when(params.getQuickPickupAodDuration()).thenReturn(500);
 
@@ -61,14 +61,13 @@
         when(config.getWakeLockScreenDebounce()).thenReturn(0L);
 
         when(config.doubleTapSensorType()).thenReturn(null);
-        when(config.tapSensorType()).thenReturn(null);
         when(config.longPressSensorType()).thenReturn(null);
         when(config.udfpsLongPressSensorType()).thenReturn(null);
         when(config.quickPickupSensorType()).thenReturn(null);
 
         when(config.tapGestureEnabled(anyInt())).thenReturn(true);
         when(config.tapSensorAvailable()).thenReturn(true);
-        when(config.tapSensorType()).thenReturn(FakeSensorManager.TAP_SENSOR_TYPE);
+        when(config.tapSensorType(anyInt())).thenReturn(FakeSensorManager.TAP_SENSOR_TYPE);
 
         when(config.dozePickupSensorAvailable()).thenReturn(false);
         when(config.wakeScreenGestureAvailable()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 5c4c27c..57ab40c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -47,6 +47,7 @@
 import com.android.systemui.doze.DozeSensors.TriggerSensor;
 import com.android.systemui.plugins.SensorManagerPlugin;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.sensors.AsyncSensorManager;
 import com.android.systemui.util.sensors.ProximitySensor;
 import com.android.systemui.util.settings.FakeSettings;
@@ -85,6 +86,8 @@
     private AuthController mAuthController;
     @Mock
     private ProximitySensor mProximitySensor;
+    private @DevicePostureController.DevicePostureInt int mDevicePosture =
+            DevicePostureController.DEVICE_POSTURE_UNKNOWN;
     private FakeSettings mFakeSettings = new FakeSettings();
     private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
     private TestableLooper mTestableLooper;
@@ -101,6 +104,7 @@
             ((Runnable) invocation.getArgument(0)).run();
             return null;
         }).when(mWakeLock).wrap(any(Runnable.class));
+        mDevicePosture = DevicePostureController.DEVICE_POSTURE_UNKNOWN;
         mDozeSensors = new TestableDozeSensors();
     }
 
@@ -157,7 +161,7 @@
         // GIVEN we only should register sensors using prox when not in low-powered mode / off
         // and the single tap sensor uses the proximity sensor
         when(mDozeParameters.getSelectivelyRegisterSensorsUsingProx()).thenReturn(true);
-        when(mDozeParameters.singleTapUsesProx()).thenReturn(true);
+        when(mDozeParameters.singleTapUsesProx(anyInt())).thenReturn(true);
         TestableDozeSensors dozeSensors = new TestableDozeSensors();
 
         // THEN on initialization, the tap sensor isn't requested
@@ -258,12 +262,25 @@
         assertTrue(triggerSensor.mRegistered);
     }
 
+    @Test
+    public void testPostureOpen_registersCorrectTapGesture() {
+        // GIVEN device posture open
+        mDevicePosture = DevicePostureController.DEVICE_POSTURE_OPENED;
+
+        // WHEN DozeSensors are initialized
+        new TestableDozeSensors();
+
+        // THEN we use the posture to determine which tap sensor to use
+        verify(mAmbientDisplayConfiguration).tapSensorType(eq(mDevicePosture));
+    }
+
     private class TestableDozeSensors extends DozeSensors {
 
         TestableDozeSensors() {
             super(getContext(), mSensorManager, mDozeParameters,
                     mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
-                    mProximitySensor, mFakeSettings, mAuthController);
+                    mProximitySensor, mFakeSettings, mAuthController,
+                    mDevicePosture);
             for (TriggerSensor sensor : mSensors) {
                 if (sensor instanceof PluginSensor
                         && ((PluginSensor) sensor).mPluginSensor.getType()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 9577c7a..b688fcc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -45,6 +45,7 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.doze.DozeTriggers.DozingUpdateUiEvent;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.concurrency.FakeThreadFactory;
@@ -86,6 +87,8 @@
     private UiEventLogger mUiEventLogger;
     @Mock
     private KeyguardStateController mKeyguardStateController;
+    @Mock
+    private DevicePostureController mDevicePostureController;
 
     private DozeTriggers mTriggers;
     private FakeSensorManager mSensors;
@@ -117,7 +120,8 @@
         mTriggers = new DozeTriggers(mContext, mHost, config, dozeParameters,
                 asyncSensorManager, wakeLock, mDockManager, mProximitySensor,
                 mProximityCheck, mock(DozeLog.class), mBroadcastDispatcher, new FakeSettings(),
-                mAuthController, mExecutor, mUiEventLogger, mKeyguardStateController);
+                mAuthController, mExecutor, mUiEventLogger, mKeyguardStateController,
+                mDevicePostureController);
         mTriggers.setDozeMachine(mMachine);
         waitForSensorManager();
     }