[automerger skipped] Fix accidental implicit fallthroughs am: fbeb4fc139 am: 85eac001da am: 89462bd0e6 -s ours am: 0d411bddad -s ours am: 49e01145d5 -s ours am: 3235fb8377 -s ours am: 6ca65c3cec -s ours am: a0563f0ce6 -s ours
am skip reason: Change-Id I818e18a995760f17b85b4c72ee577e531fa2a601 with SHA-1 540824e658 is in history

Change-Id: Ifaa4896d7d58e38ba470ffdf0ef56417386a463f
diff --git a/include/hardware/hwcomposer2.h b/include/hardware/hwcomposer2.h
index c70aef6..6400a7c 100644
--- a/include/hardware/hwcomposer2.h
+++ b/include/hardware/hwcomposer2.h
@@ -50,6 +50,11 @@
      * the device may return -1 instead */
     HWC2_ATTRIBUTE_DPI_X = 4,
     HWC2_ATTRIBUTE_DPI_Y = 5,
+
+    /* The configuration group this config is associated to.
+     * Switching between configurations within the same group may be done seamlessly
+     * in some conditions via setActiveConfigWithConstraints. */
+    HWC2_ATTRIBUTE_CONFIG_GROUP = 7,
 } hwc2_attribute_t;
 
 /* Blend modes, settable per layer */
@@ -73,6 +78,8 @@
     HWC2_CALLBACK_HOTPLUG = 1,
     HWC2_CALLBACK_REFRESH = 2,
     HWC2_CALLBACK_VSYNC = 3,
+    HWC2_CALLBACK_VSYNC_2_4 = 4,
+    HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED = 5,
 } hwc2_callback_descriptor_t;
 
 /* Optional capabilities which may be supported by some devices. The particular
@@ -203,6 +210,12 @@
     HWC2_DISPLAY_TYPE_VIRTUAL = 2,
 } hwc2_display_type_t;
 
+/* Physical display types returned by getDisplayConnectionType */
+typedef enum {
+    HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL = 0,
+    HWC2_DISPLAY_CONNECTION_TYPE_EXTERNAL = 1,
+} hwc2_display_connection_type_t;
+
 /* Return codes from all functions */
 typedef enum {
     HWC2_ERROR_NONE = 0,
@@ -214,6 +227,8 @@
     HWC2_ERROR_NO_RESOURCES,
     HWC2_ERROR_NOT_VALIDATED,
     HWC2_ERROR_UNSUPPORTED,
+    HWC2_ERROR_SEAMLESS_NOT_ALLOWED,
+    HWC2_ERROR_SEAMLESS_NOT_POSSIBLE,
 } hwc2_error_t;
 
 /* Function descriptors for use with getFunction */
@@ -282,6 +297,11 @@
     HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS,
     HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT,
     HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS,
+
+    // composer 2.4
+    HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE,
+    HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD,
+    HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS,
 } hwc2_function_descriptor_t;
 
 /* Layer requests returned from getDisplayRequests */
@@ -428,6 +448,7 @@
         case HWC2_ATTRIBUTE_VSYNC_PERIOD: return "VsyncPeriod";
         case HWC2_ATTRIBUTE_DPI_X: return "DpiX";
         case HWC2_ATTRIBUTE_DPI_Y: return "DpiY";
+        case HWC2_ATTRIBUTE_CONFIG_GROUP: return "ConfigGroup";
         default: return "Unknown";
     }
 }
@@ -449,6 +470,8 @@
         case HWC2_CALLBACK_HOTPLUG: return "Hotplug";
         case HWC2_CALLBACK_REFRESH: return "Refresh";
         case HWC2_CALLBACK_VSYNC: return "Vsync";
+        case HWC2_CALLBACK_VSYNC_2_4: return "Vsync2.4";
+        case HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED: return "VsyncPeriodTimingChanged";
         default: return "Unknown";
     }
 }
@@ -509,6 +532,14 @@
     }
 }
 
+static inline const char* getDisplayConnectionTypeName(hwc2_display_connection_type_t type) {
+    switch (type) {
+        case HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL: return "Internal";
+        case HWC2_DISPLAY_CONNECTION_TYPE_EXTERNAL: return "External";
+        default: return "Unknown";
+    }
+}
+
 static inline const char* getErrorName(hwc2_error_t error) {
     switch (error) {
         case HWC2_ERROR_NONE: return "None";
@@ -520,6 +551,8 @@
         case HWC2_ERROR_NO_RESOURCES: return "NoResources";
         case HWC2_ERROR_NOT_VALIDATED: return "NotValidated";
         case HWC2_ERROR_UNSUPPORTED: return "Unsupported";
+        case HWC2_ERROR_SEAMLESS_NOT_ALLOWED: return "SeamlessNotAllowed";
+        case HWC2_ERROR_SEAMLESS_NOT_POSSIBLE: return "SeamlessNotPossible";
         default: return "Unknown";
     }
 }
@@ -602,6 +635,12 @@
         case HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS: return "SetLayerPerFrameMetadataBlobs";
         case HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT: return "GetDisplayBrightnessSupport";
         case HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS: return "SetDisplayBrightness";
+
+        // composer 2.4
+        case HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE: return "GetDisplayConnectionType";
+        case HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD: return "GetDisplayVsyncPeriod";
+        case HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS: return "SetActiveConfigWithConstraints";
+
         default: return "Unknown";
     }
 }
@@ -708,6 +747,7 @@
     VsyncPeriod = HWC2_ATTRIBUTE_VSYNC_PERIOD,
     DpiX = HWC2_ATTRIBUTE_DPI_X,
     DpiY = HWC2_ATTRIBUTE_DPI_Y,
+    ConfigGroup = HWC2_ATTRIBUTE_CONFIG_GROUP,
 };
 TO_STRING(hwc2_attribute_t, Attribute, getAttributeName)
 
@@ -724,6 +764,8 @@
     Hotplug = HWC2_CALLBACK_HOTPLUG,
     Refresh = HWC2_CALLBACK_REFRESH,
     Vsync = HWC2_CALLBACK_VSYNC,
+    Vsync_2_4 = HWC2_CALLBACK_VSYNC_2_4,
+    VsyncPeriodTimingChanged = HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED,
 };
 TO_STRING(hwc2_callback_descriptor_t, Callback, getCallbackDescriptorName)
 
@@ -767,6 +809,12 @@
 };
 TO_STRING(hwc2_display_type_t, DisplayType, getDisplayTypeName)
 
+enum class DisplayConnectionType : uint32_t {
+    Internal = HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL,
+    External = HWC2_DISPLAY_CONNECTION_TYPE_EXTERNAL,
+};
+TO_STRING(hwc2_display_connection_type_t, DisplayConnectionType, getDisplayConnectionTypeName)
+
 enum class Error : int32_t {
     None = HWC2_ERROR_NONE,
     BadConfig = HWC2_ERROR_BAD_CONFIG,
@@ -777,6 +825,8 @@
     NoResources = HWC2_ERROR_NO_RESOURCES,
     NotValidated = HWC2_ERROR_NOT_VALIDATED,
     Unsupported = HWC2_ERROR_UNSUPPORTED,
+    SeamlessNotAllowed = HWC2_ERROR_SEAMLESS_NOT_ALLOWED,
+    SeamlessNotPossible = HWC2_ERROR_SEAMLESS_NOT_POSSIBLE,
 };
 TO_STRING(hwc2_error_t, Error, getErrorName)
 
@@ -845,6 +895,12 @@
     SetLayerPerFrameMetadataBlobs = HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS,
     GetDisplayBrightnessSupport = HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT,
     SetDisplayBrightness = HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS,
+
+    // composer 2.4
+    GetDisplayConnectionType = HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE,
+    GetDisplayVsyncPeriod = HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD,
+    SetActiveConfigWithConstraints = HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS,
+
 };
 TO_STRING(hwc2_function_descriptor_t, FunctionDescriptor,
         getFunctionDescriptorName)
@@ -904,6 +960,7 @@
 typedef uint32_t hwc2_config_t;
 typedef uint64_t hwc2_display_t;
 typedef uint64_t hwc2_layer_t;
+typedef uint32_t hwc2_vsync_period_t;
 
 /*
  * Device Struct
@@ -1030,6 +1087,47 @@
 typedef void (*HWC2_PFN_VSYNC)(hwc2_callback_data_t callbackData,
         hwc2_display_t display, int64_t timestamp);
 
+/* vsync_2_4(..., display, timestamp, vsyncPeriodNanos)
+ * Descriptor: HWC2_CALLBACK_VSYNC_2_4
+ * Required for HWC2 devices for composer 2.4
+ *
+ * Notifies the client that a vsync event has occurred. This callback must
+ * only be triggered when vsync is enabled for this display (through
+ * setVsyncEnabled).
+ *
+ * This callback should be triggered from a thread of at least
+ * HAL_PRIORITY_URGENT_DISPLAY with as little latency as possible, typically
+ * less than 0.5 ms. This thread is guaranteed not to call back into the device.
+ *
+ * Parameters:
+ *   display - the display which has received a vsync event
+ *   timestamp - the CLOCK_MONOTONIC time at which the vsync event occurred, in
+ *       nanoseconds
+ *   vsyncPeriodNanos - the display vsync period in nanoseconds i.e. the next onVsync2_4 is
+ *   expected to be called vsyncPeriod nanoseconds after this call.
+ */
+typedef void (*HWC2_PFN_VSYNC_2_4)(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int64_t timestamp, hwc2_vsync_period_t vsyncPeriodNanos);
+
+/* vsyncPeriodTimingChanged(..., display, updated_timeline)
+ * Descriptor: HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED
+ * Optional for HWC2 devices for composer 2.4
+ *
+ * Notifies the client that the previously reported timing for vsync period change has been
+ * updated. This may occur if the composer missed the deadline for changing the vsync period
+ * or the client submitted a refresh frame too late.
+ *
+ * This callback should be triggered from a thread of at least
+ * HAL_PRIORITY_URGENT_DISPLAY with as little latency as possible, typically
+ * less than 0.5 ms. This thread is guaranteed not to call back into the device.
+ *
+ * Parameters:
+ *   display - the display which has received a vsync event
+ *   updated_timeline - new timeline for the vsync period change
+ */
+typedef void (*HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED)(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, hwc_vsync_period_change_timeline_t* updated_timeline);
+
 /*
  * Device Functions
  *
@@ -2727,6 +2825,85 @@
 typedef int32_t /*hwc_error_t*/ (*HWC2_PFN_SET_DISPLAY_BRIGHTNESS)(hwc2_device_t* device,
         hwc2_display_t display, float brightness);
 
+/* getDisplayConnectionType(..., outType)
+ * Descriptor: HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE
+ * Optional for all HWC2 devices
+ *
+ * Returns whether the given physical display is internal or external.
+ *
+ * Parameters:
+ *   outType - the connection type of the display; pointer will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY when the display is invalid or virtual.
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE)(
+        hwc2_device_t* device, hwc2_display_t display,
+        uint32_t* /*hwc2_display_connection_type_t*/ outType);
+
+/* getDisplayVsyncPeriod(..., outVsyncPeriods)
+ * Descriptor: HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD
+ * Required for HWC2 devices for composer 2.4
+ *
+ * Retrieves which vsync period the display is currently using.
+ *
+ * If no display configuration is currently active, this function must
+ * return BAD_CONFIG. If a vsync period is about to change due to a
+ * setActiveConfigWithConstraints call, this function must return the current vsync period
+ * until the change has taken place.
+ *
+ * Parameters:
+ *     outVsyncPeriod - the current vsync period of the display.
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_CONFIG - no configuration is currently active
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_vsync_period_t* outVsyncPeriod);
+
+/* setActiveConfigWithConstraints(...,
+ *                                config,
+ *                                vsyncPeriodChangeConstraints,
+ *                                outTimeline)
+ * Descriptor: HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS
+ * Required for HWC2 devices for composer 2.4
+ *
+ * Sets the active configuration and the refresh rate for this display.
+ * If the new config shares the same config group as the current config,
+ * only the vsync period shall change.
+ * Upon returning, the given display configuration, except vsync period, must be active and
+ * remain so until either this function is called again or the display is disconnected.
+ * When the display starts to refresh at the new vsync period, onVsync_2_4 callback must be
+ * called with the new vsync period.
+ *
+ * Parameters:
+ *     config - the new display configuration.
+ *     vsyncPeriodChangeConstraints - constraints required for changing vsync period:
+ *                                    desiredTimeNanos - the time in CLOCK_MONOTONIC after
+ *                                                       which the vsync period may change
+ *                                                       (i.e., the vsync period must not change
+ *                                                       before this time).
+ *                                    seamlessRequired - if true, requires that the vsync period
+ *                                                       change must happen seamlessly without
+ *                                                       a noticeable visual artifact.
+ *     outTimeline - the timeline for the vsync period change.
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in.
+ *   HWC2_ERROR_BAD_CONFIG - an invalid configuration handle passed in.
+ *   HWC2_ERROR_SEAMLESS_NOT_ALLOWED - when seamlessRequired was true but config provided doesn't
+     *                                 share the same config group as the current config.
+ *   HWC2_ERROR_SEAMLESS_NOT_POSSIBLE - when seamlessRequired was true but the display cannot
+ *                                      achieve the vsync period change without a noticeable
+ *                                      visual artifact.
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config,
+        hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
+        hwc_vsync_period_change_timeline_t* outTimeline);
+
+
 __END_DECLS
 
 #endif
diff --git a/include/hardware/hwcomposer_defs.h b/include/hardware/hwcomposer_defs.h
index fd373e3..db81c51 100644
--- a/include/hardware/hwcomposer_defs.h
+++ b/include/hardware/hwcomposer_defs.h
@@ -250,6 +250,11 @@
     /* Indicates which of the vendor-defined color transforms is provided by
      * this configuration. */
     HWC_DISPLAY_COLOR_TRANSFORM             = 6,
+
+    /* The configuration group this config is associated to. The groups are defined
+     * to mark certain configs as similar and changing configs within a certain group
+     * may be done seamlessly in some conditions. setActiveConfigWithConstraints. */
+    HWC_DISPLAY_CONFIG_GROUP                = 7,
 };
 
 /* Allowed events for hwc_methods::eventControl() */
@@ -299,6 +304,32 @@
     HWC_POWER_MODE_DOZE_SUSPEND  = 3,
 };
 
+/* Constraints for changing vsync period */
+typedef struct hwc_vsync_period_change_constraints {
+    /* Time in CLOCK_MONOTONIC after which the vsync period may change
+     * (i.e., the vsync period must not change before this time). */
+    int64_t desiredTimeNanos;
+    /*
+     * If true, requires that the vsync period change must happen seamlessly without
+     * a noticeable visual artifact. */
+    uint8_t seamlessRequired;
+} hwc_vsync_period_change_constraints_t;
+
+/* Timing for a vsync period change. */
+typedef struct hwc_vsync_period_change_timeline {
+    /* The time in CLOCK_MONOTONIC when the new display will start to refresh at
+     * the new vsync period. */
+    int64_t newVsyncAppliedTimeNanos;
+
+    /* Set to true if the client is required to sent a frame to be displayed before
+     * the change can take place. */
+    uint8_t refreshRequired;
+
+    /* The time in CLOCK_MONOTONIC when the client is expected to send the new frame.
+     * Should be ignored if refreshRequired is false. */
+    int64_t refreshTimeNanos;
+} hwc_vsync_period_change_timeline_t;
+
 /*****************************************************************************/
 
 __END_DECLS
diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp
index dda0d0e..103f57d 100644
--- a/modules/audio_remote_submix/audio_hw.cpp
+++ b/modules/audio_remote_submix/audio_hw.cpp
@@ -821,12 +821,22 @@
         return 0;
     }
 
-    // If the write to the sink would block when no input stream is present, flush enough frames
+    // If the write to the sink would block, flush enough frames
     // from the pipe to make space to write the most recent data.
+    // We DO NOT block if:
+    // - no peer input stream is present
+    // - the peer input is in standby AFTER having been active.
+    // We DO block if:
+    // - the input was never activated to avoid discarding first frames
+    // in the pipe in case capture start was delayed
     {
         const size_t availableToWrite = sink->availableToWrite();
+        // NOTE: rsxSink has been checked above and sink and source life cycles are synchronized
         sp<MonoPipeReader> source = rsxadev->routes[out->route_handle].rsxSource;
-        if (rsxadev->routes[out->route_handle].input == NULL && availableToWrite < frames) {
+        const struct submix_stream_in *in = rsxadev->routes[out->route_handle].input;
+        const bool dont_block = (in == NULL)
+                || (in->input_standby && (in->read_counter_frames != 0));
+        if (dont_block && availableToWrite < frames) {
             static uint8_t flush_buffer[64];
             const size_t flushBufferSizeFrames = sizeof(flush_buffer) / frame_size;
             size_t frames_to_flush_from_source = frames - availableToWrite;
@@ -896,8 +906,14 @@
 
     int ret = -EWOULDBLOCK;
     pthread_mutex_lock(&rsxadev->lock);
-    const ssize_t frames_in_pipe =
-            rsxadev->routes[out->route_handle].rsxSource->availableToRead();
+    sp<MonoPipeReader> source = rsxadev->routes[out->route_handle].rsxSource;
+    if (source == NULL) {
+        ALOGW("%s called on released output", __FUNCTION__);
+        pthread_mutex_unlock(&rsxadev->lock);
+        return -ENODEV;
+    }
+
+    const ssize_t frames_in_pipe = source->availableToRead();
     if (CC_UNLIKELY(frames_in_pipe < 0)) {
         *frames = out->frames_written;
         ret = 0;
@@ -930,8 +946,14 @@
     struct submix_audio_device * const rsxadev = out->dev;
 
     pthread_mutex_lock(&rsxadev->lock);
-    const ssize_t frames_in_pipe =
-            rsxadev->routes[out->route_handle].rsxSource->availableToRead();
+    sp<MonoPipeReader> source = rsxadev->routes[out->route_handle].rsxSource;
+    if (source == NULL) {
+        ALOGW("%s called on released output", __FUNCTION__);
+        pthread_mutex_unlock(&rsxadev->lock);
+        return -ENODEV;
+    }
+
+    const ssize_t frames_in_pipe = source->availableToRead();
     if (CC_UNLIKELY(frames_in_pipe < 0)) {
         *dsp_frames = (uint32_t)out->frames_written_since_standby;
     } else {