Merge changes Ib7227f18,I96926932,I46476112,I2c17b1e4,I47ee9e39, ... am: c809601217 am: 534edb5808
am: cf5c9d616c

Change-Id: I7adf6faf859354ddd1cb93b143514c2ae16152ea
diff --git a/hardware.c b/hardware.c
index 40ae1d1..6e72ce9 100644
--- a/hardware.c
+++ b/hardware.c
@@ -24,6 +24,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 
 #define LOG_TAG "HAL"
@@ -148,6 +149,25 @@
 }
 
 /*
+ * If path is in in_path.
+ */
+static bool path_in_path(const char *path, const char *in_path) {
+    char real_path[PATH_MAX];
+    if (realpath(path, real_path) == NULL) return false;
+
+    char real_in_path[PATH_MAX];
+    if (realpath(in_path, real_in_path) == NULL) return false;
+
+    const size_t real_in_path_len = strlen(real_in_path);
+    if (strncmp(real_path, real_in_path, real_in_path_len) != 0) {
+        return false;
+    }
+
+    return strlen(real_path) > real_in_path_len &&
+        real_path[real_in_path_len] == '/';
+}
+
+/*
  * Check if a HAL with given name and subname exists, if so return 0, otherwise
  * otherwise return negative.  On success path will contain the path to the HAL.
  */
@@ -156,18 +176,18 @@
 {
     snprintf(path, path_len, "%s/%s.%s.so",
              HAL_LIBRARY_PATH3, name, subname);
-    if (access(path, R_OK) == 0)
+    if (path_in_path(path, HAL_LIBRARY_PATH3) && access(path, R_OK) == 0)
         return 0;
 
     snprintf(path, path_len, "%s/%s.%s.so",
              HAL_LIBRARY_PATH2, name, subname);
-    if (access(path, R_OK) == 0)
+    if (path_in_path(path, HAL_LIBRARY_PATH2) && access(path, R_OK) == 0)
         return 0;
 
 #ifndef __ANDROID_VNDK__
     snprintf(path, path_len, "%s/%s.%s.so",
              HAL_LIBRARY_PATH1, name, subname);
-    if (access(path, R_OK) == 0)
+    if (path_in_path(path, HAL_LIBRARY_PATH1) && access(path, R_OK) == 0)
         return 0;
 #endif
 
diff --git a/include/hardware/hwcomposer2.h b/include/hardware/hwcomposer2.h
index c9809ce..71831a0 100644
--- a/include/hardware/hwcomposer2.h
+++ b/include/hardware/hwcomposer2.h
@@ -270,7 +270,8 @@
     HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE,
     HWC2_FUNCTION_GET_RENDER_INTENTS,
     HWC2_FUNCTION_SET_COLOR_MODE_WITH_RENDER_INTENT,
-    HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX
+    HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX,
+    HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA
 } hwc2_function_descriptor_t;
 
 /* Layer requests returned from getDisplayRequests */
@@ -524,6 +525,7 @@
         case HWC2_FUNCTION_GET_RENDER_INTENTS: return "GetRenderIntents";
         case HWC2_FUNCTION_SET_COLOR_MODE_WITH_RENDER_INTENT: return "SetColorModeWithRenderIntent";
         case HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX: return "GetDataspaceSaturationMatrix";
+        case HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA: return "GetDisplayIdentificationData";
         default: return "Unknown";
     }
 }
@@ -722,6 +724,7 @@
     GetRenderIntents = HWC2_FUNCTION_GET_RENDER_INTENTS,
     SetColorModeWithRenderIntent = HWC2_FUNCTION_SET_COLOR_MODE_WITH_RENDER_INTENT,
     GetDataspaceSaturationMatrix = HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX,
+    GetDisplayIdentificationData = HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA,
 };
 TO_STRING(hwc2_function_descriptor_t, FunctionDescriptor,
         getFunctionDescriptorName)
@@ -1374,6 +1377,35 @@
         hwc2_device_t* device, hwc2_display_t display,
         int32_t* /*hwc2_display_type_t*/ outType);
 
+/* getDisplayIdentificationData(..., outPort, outDataSize, outData)
+ * Descriptor: HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA
+ * Optional for HWC2 devices
+ *
+ * If supported, getDisplayIdentificationData returns the port and data that
+ * describe a physical display. The port is a unique number that identifies a
+ * physical connector (e.g. eDP, HDMI) for display output. The data blob is
+ * parsed to determine its format, typically EDID 1.3 as specified in VESA
+ * E-EDID Standard Release A Revision 1.
+ *
+ * Devices for which display identification is unsupported must return null when
+ * getFunction is called with HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA.
+ *
+ * Parameters:
+ *   outPort - the connector to which the display is connected;
+ *             pointer will be non-NULL
+ *   outDataSize - if outData is NULL, the size in bytes of the data which would
+ *       have been returned; if outData is not NULL, the size of outData, which
+ *       must not exceed the value stored in outDataSize prior to the call;
+ *       pointer will be non-NULL
+ *   outData - the EDID 1.3 blob identifying the display
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA)(
+        hwc2_device_t* device, hwc2_display_t display, uint8_t* outPort,
+        uint32_t* outDataSize, uint8_t* outData);
+
 /* getDozeSupport(..., outSupport)
  * Descriptor: HWC2_FUNCTION_GET_DOZE_SUPPORT
  * Must be provided by all HWC2 devices
diff --git a/modules/usbaudio/audio_hal.c b/modules/usbaudio/audio_hal.c
index 81c9fd6..d797a21 100644
--- a/modules/usbaudio/audio_hal.c
+++ b/modules/usbaudio/audio_hal.c
@@ -47,6 +47,9 @@
 /* Lock play & record samples rates at or above this threshold */
 #define RATELOCK_THRESHOLD 96000
 
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
 struct audio_device {
     struct audio_hw_device hw_device;
 
@@ -62,7 +65,7 @@
 
     /* lock input & output sample rates */
     /*FIXME - How do we address multiple output streams? */
-    uint32_t device_sample_rate;
+    uint32_t device_sample_rate;    // this should be a rate that is common to both input & output
 
     bool mic_muted;
 
@@ -597,6 +600,7 @@
         ret = -EINVAL;
     }
 
+    /* TODO: This is a problem if the input does not support this rate */
     out->adev->device_sample_rate = config->sample_rate;
     device_unlock(out->adev);
 
@@ -929,6 +933,19 @@
     return 0;
 }
 
+static int in_get_capture_position(const struct audio_stream_in *stream,
+                                   int64_t *frames, int64_t *time)
+{
+    struct stream_in *in = (struct stream_in *)stream; // discard const qualifier
+    stream_lock(&in->lock);
+
+    const alsa_device_proxy *proxy = &in->proxy;
+    const int ret = proxy_get_capture_position(proxy, frames, time);
+
+    stream_unlock(&in->lock);
+    return ret;
+}
+
 static int adev_open_input_stream(struct audio_hw_device *hw_dev,
                                   audio_io_handle_t handle,
                                   audio_devices_t devicesSpec __unused,
@@ -972,6 +989,7 @@
     in->stream.set_gain = in_set_gain;
     in->stream.read = in_read;
     in->stream.get_input_frames_lost = in_get_input_frames_lost;
+    in->stream.get_capture_position = in_get_capture_position;
 
     stream_lock_init(&in->lock);
 
@@ -1008,20 +1026,36 @@
     }
 
     /* Rate */
+    int request_config_rate = config->sample_rate;
     if (config->sample_rate == 0) {
         config->sample_rate = profile_get_default_sample_rate(in->profile);
     }
 
-    if (in->adev->device_sample_rate != 0 &&                 /* we are playing, so lock the rate */
+    if (in->adev->device_sample_rate != 0 &&   /* we are playing, so lock the rate if possible */
         in->adev->device_sample_rate >= RATELOCK_THRESHOLD) {/* but only for high sample rates */
-        ret = config->sample_rate != in->adev->device_sample_rate ? -EINVAL : 0;
-        proxy_config.rate = config->sample_rate = in->adev->device_sample_rate;
+        if (config->sample_rate != in->adev->device_sample_rate) {
+            unsigned highest_rate = profile_get_highest_sample_rate(in->profile);
+            if (highest_rate == 0) {
+                ret = -EINVAL; /* error with device */
+            } else {
+                proxy_config.rate = config->sample_rate =
+                        min(highest_rate, in->adev->device_sample_rate);
+                if (request_config_rate != 0 && proxy_config.rate != config->sample_rate) {
+                    /* Changing the requested rate */
+                    ret = -EINVAL;
+                } else {
+                    /* Everything AOK! */
+                    ret = 0;
+                }
+            }
+        }
     } else if (profile_is_sample_rate_valid(in->profile, config->sample_rate)) {
         proxy_config.rate = config->sample_rate;
     } else {
         proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
         ret = -EINVAL;
     }
+
     device_unlock(in->adev);
 
     /* Format */