diff options
-rw-r--r-- | include/hardware/fingerprint.h | 82 | ||||
-rw-r--r-- | include/hardware/gatekeeper.h | 29 | ||||
-rw-r--r-- | include/hardware/keymaster_defs.h | 73 | ||||
-rw-r--r-- | include/hardware/sensors.h | 31 | ||||
-rw-r--r-- | modules/usbaudio/audio_hal.c | 77 |
5 files changed, 185 insertions, 107 deletions
diff --git a/include/hardware/fingerprint.h b/include/hardware/fingerprint.h index fd0d8f3..075e18b 100644 --- a/include/hardware/fingerprint.h +++ b/include/hardware/fingerprint.h @@ -102,6 +102,35 @@ typedef struct fingerprint_device { struct hw_device_t common; /* + * Client provided callback function to receive notifications. + * Do not set by hand, use the function above instead. + */ + fingerprint_notify_t notify; + + /* + * Set notification callback: + * Registers a user function that would receive notifications from the HAL + * The call will block if the HAL state machine is in busy state until HAL + * leaves the busy state. + * + * Function return: 0 if callback function is successfuly registered + * or a negative number in case of error, generally from the errno.h set. + */ + int (*set_notify)(struct fingerprint_device *dev, fingerprint_notify_t notify); + + /* + * Fingerprint pre-enroll enroll request: + * Generates a unique token to upper layers to indicate the start of an enrollment transaction. + * This token will be wrapped by security for verification and passed to enroll() for + * verification before enrollment will be allowed. This is to ensure adding a new fingerprint + * template was preceded by some kind of credential confirmation (e.g. device password). + * + * Function return: 0 if function failed + * otherwise, a uint64_t of token + */ + uint64_t (*pre_enroll)(struct fingerprint_device *dev); + + /* * Fingerprint enroll request: * Switches the HAL state machine to collect and store a new fingerprint * template. Switches back as soon as enroll is complete @@ -112,23 +141,21 @@ typedef struct fingerprint_device { * to supply the gid or set it to 0 in which case a unique group id will be generated. * * Function return: 0 if enrollment process can be successfully started - * -1 otherwise. A notify() function may be called - * indicating the error condition. + * or a negative number in case of error, generally from the errno.h set. + * A notify() function may be called indicating the error condition. */ int (*enroll)(struct fingerprint_device *dev, const hw_auth_token_t *hat, uint32_t gid, uint32_t timeout_sec); /* - * Fingerprint pre-enroll enroll request: - * Generates a unique token to upper layers to indicate the start of an enrollment transaction. - * This token will be wrapped by security for verification and passed to enroll() for - * verification before enrollment will be allowed. This is to ensure adding a new fingerprint - * template was preceded by some kind of credential confirmation (e.g. device password). + * Finishes the enroll operation and invalidates the pre_enroll() generated challenge. + * This will be called at the end of a multi-finger enrollment session to indicate + * that no more fingers will be added. * - * Function return: 0 if function failed - * otherwise, a uint64_t of token + * Function return: 0 if the request is accepted + * or a negative number in case of error, generally from the errno.h set. */ - uint64_t (*pre_enroll)(struct fingerprint_device *dev); + int (*post_enroll)(struct fingerprint_device *dev); /* * get_authenticator_id: @@ -136,17 +163,17 @@ typedef struct fingerprint_device { * change whenever a new fingerprint is enrolled, thus creating a new fingerprint * set. * - * Function return: current authenticator id. + * Function return: current authenticator id or 0 if function failed. */ uint64_t (*get_authenticator_id)(struct fingerprint_device *dev); /* * Cancel pending enroll or authenticate, sending FINGERPRINT_ERROR_CANCELED * to all running clients. Switches the HAL state machine back to the idle state. - * will indicate switch back to the scan mode. + * Unlike enroll_done() doesn't invalidate the pre_enroll() challenge. * * Function return: 0 if cancel request is accepted - * -1 otherwise. + * or a negative number in case of error, generally from the errno.h set. */ int (*cancel)(struct fingerprint_device *dev); @@ -165,9 +192,8 @@ typedef struct fingerprint_device { * The caller of this function has a complete list of the templates when *max_size * is the same as the function return. * - * Function return: Total number of fingerprint templates in the current - storage directory. - * -1 on error. + * Function return: Total number of fingerprint templates in the current storage directory. + * or a negative number in case of error, generally from the errno.h set. */ int (*enumerate)(struct fingerprint_device *dev, fingerprint_finger_id_t *results, uint32_t *max_size); @@ -181,7 +207,7 @@ typedef struct fingerprint_device { * fingerprint_msg.data.removed.id indicating the template id removed. * * Function return: 0 if fingerprint template(s) can be successfully deleted - * -1 otherwise. + * or a negative number in case of error, generally from the errno.h set. */ int (*remove)(struct fingerprint_device *dev, uint32_t gid, uint32_t fid); @@ -192,7 +218,7 @@ typedef struct fingerprint_device { * data directory. * * Function return: 0 on success - * -1 if the group does not exist. + * or a negative number in case of error, generally from the errno.h set. */ int (*set_active_group)(struct fingerprint_device *dev, uint32_t gid, const char *store_path); @@ -201,26 +227,12 @@ typedef struct fingerprint_device { * Authenticates an operation identifed by operation_id * * Function return: 0 on success - * -1 if the operation cannot be completed + * or a negative number in case of error, generally from the errno.h set. */ int (*authenticate)(struct fingerprint_device *dev, uint64_t operation_id, uint32_t gid); - /* - * Set notification callback: - * Registers a user function that would receive notifications from the HAL - * The call will block if the HAL state machine is in busy state until HAL - * leaves the busy state. - * - * Function return: 0 if callback function is successfuly registered - * -1 otherwise. - */ - int (*set_notify)(struct fingerprint_device *dev, fingerprint_notify_t notify); - - /* - * Client provided callback function to receive notifications. - * Do not set by hand, use the function above instead. - */ - fingerprint_notify_t notify; + /* Reserved for backward binary compatibility */ + void *reserved[4]; } fingerprint_device_t; typedef struct fingerprint_module { diff --git a/include/hardware/gatekeeper.h b/include/hardware/gatekeeper.h index 6d2fb0b..2bb2b08 100644 --- a/include/hardware/gatekeeper.h +++ b/include/hardware/gatekeeper.h @@ -143,7 +143,36 @@ struct gatekeeper_device { const uint8_t *provided_password, uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll); + /* + * Deletes the enrolled_password_handle associated wth the uid. Once deleted + * the user cannot be verified anymore. + * This function is optional and should be set to NULL if it is not implemented. + * + * Parameters + * - dev: pointer to gatekeeper_device acquired via calls to gatekeeper_open + * - uid: the Android user identifier + * + * Returns: + * - 0 on success + * - An error code < 0 on failure + */ + int (*delete_user)(const struct gatekeeper_device *dev, uint32_t uid); + + /* + * Deletes all the enrolled_password_handles for all uid's. Once called, + * no users will be enrolled on the device. + * This function is optional and should be set to NULL if it is not implemented. + * + * Parameters + * - dev: pointer to gatekeeper_device acquired via calls to gatekeeper_open + * + * Returns: + * - 0 on success + * - An error code < 0 on failure + */ + int (*delete_all_users)(const struct gatekeeper_device *dev); }; + typedef struct gatekeeper_device gatekeeper_device_t; static inline int gatekeeper_open(const struct hw_module_t *module, diff --git a/include/hardware/keymaster_defs.h b/include/hardware/keymaster_defs.h index 77067d5..32374f1 100644 --- a/include/hardware/keymaster_defs.h +++ b/include/hardware/keymaster_defs.h @@ -34,14 +34,14 @@ typedef enum { KM_INVALID = 0 << 28, /* Invalid type, used to designate a tag as uninitialized */ KM_ENUM = 1 << 28, KM_ENUM_REP = 2 << 28, /* Repeatable enumeration value. */ - KM_INT = 3 << 28, - KM_INT_REP = 4 << 28, /* Repeatable integer value */ - KM_LONG = 5 << 28, + KM_UINT = 3 << 28, + KM_UINT_REP = 4 << 28, /* Repeatable integer value */ + KM_ULONG = 5 << 28, KM_DATE = 6 << 28, KM_BOOL = 7 << 28, KM_BIGNUM = 8 << 28, KM_BYTES = 9 << 28, - KM_LONG_REP = 10 << 28, /* Repeatable long value */ + KM_ULONG_REP = 10 << 28, /* Repeatable long value */ } keymaster_tag_type_t; typedef enum { @@ -54,14 +54,14 @@ typedef enum { /* Crypto parameters */ KM_TAG_PURPOSE = KM_ENUM_REP | 1, /* keymaster_purpose_t. */ KM_TAG_ALGORITHM = KM_ENUM | 2, /* keymaster_algorithm_t. */ - KM_TAG_KEY_SIZE = KM_INT | 3, /* Key size in bits. */ + KM_TAG_KEY_SIZE = KM_UINT | 3, /* Key size in bits. */ KM_TAG_BLOCK_MODE = KM_ENUM_REP | 4, /* keymaster_block_mode_t. */ KM_TAG_DIGEST = KM_ENUM_REP | 5, /* keymaster_digest_t. */ KM_TAG_PADDING = KM_ENUM_REP | 6, /* keymaster_padding_t. */ KM_TAG_CALLER_NONCE = KM_BOOL | 7, /* Allow caller to specify nonce or IV. */ /* Algorithm-specific. */ - KM_TAG_RSA_PUBLIC_EXPONENT = KM_LONG | 200, /* Defaults to 2^16+1 */ + KM_TAG_RSA_PUBLIC_EXPONENT = KM_ULONG | 200, /* Other hardware-enforced. */ KM_TAG_BLOB_USAGE_REQUIREMENTS = KM_ENUM | 301, /* keymaster_key_blob_usage_requirements_t */ @@ -78,34 +78,32 @@ typedef enum { longer be created. */ KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402, /* Date when existing "messages" should no longer be trusted. */ - KM_TAG_MIN_SECONDS_BETWEEN_OPS = KM_INT | 403, /* Minimum elapsed time between + KM_TAG_MIN_SECONDS_BETWEEN_OPS = KM_UINT | 403, /* Minimum elapsed time between cryptographic operations with the key. */ - KM_TAG_MAX_USES_PER_BOOT = KM_INT | 404, /* Number of times the key can be used per + KM_TAG_MAX_USES_PER_BOOT = KM_UINT | 404, /* Number of times the key can be used per boot. */ /* User authentication */ - KM_TAG_ALL_USERS = KM_BOOL | 500, /* If key is usable by all users. */ - KM_TAG_USER_ID = KM_INT | 501, /* ID of authorized user. Disallowed if - KM_TAG_ALL_USERS is present. */ - KM_TAG_USER_SECURE_ID = KM_LONG_REP | 502, /* Secure ID of authorized user or authenticator(s). - Disallowed if KM_TAG_ALL_USERS or - KM_TAG_NO_AUTH_REQUIRED is present. */ - KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503, /* If key is usable without authentication. */ - KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504, /* Bitmask of authenticator types allowed when - * KM_TAG_USER_SECURE_ID contains a secure user ID, - * rather than a secure authenticator ID. Defined in - * hw_authenticator_type_t in hw_auth_token.h. */ - KM_TAG_AUTH_TIMEOUT = KM_INT | 505, /* Required freshness of user authentication for - private/secret key operations, in seconds. - Public key operations require no authentication. - If absent, authentication is required for every - use. Authentication state is lost when the - device is powered off. */ + KM_TAG_ALL_USERS = KM_BOOL | 500, /* Reserved for future use -- ignore */ + KM_TAG_USER_ID = KM_UINT | 501, /* Reserved for future use -- ignore */ + KM_TAG_USER_SECURE_ID = KM_ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s). + Disallowed if KM_TAG_ALL_USERS or + KM_TAG_NO_AUTH_REQUIRED is present. */ + KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503, /* If key is usable without authentication. */ + KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504, /* Bitmask of authenticator types allowed when + * KM_TAG_USER_SECURE_ID contains a secure user ID, + * rather than a secure authenticator ID. Defined in + * hw_authenticator_type_t in hw_auth_token.h. */ + KM_TAG_AUTH_TIMEOUT = KM_UINT | 505, /* Required freshness of user authentication for + private/secret key operations, in seconds. + Public key operations require no authentication. + If absent, authentication is required for every + use. Authentication state is lost when the + device is powered off. */ /* Application access control */ - KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600, /* If key is usable by all applications. */ - KM_TAG_APPLICATION_ID = KM_BYTES | 601, /* ID of authorized application. Disallowed if - KM_TAG_ALL_APPLICATIONS is present. */ + KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600, /* Reserved for future use -- ignore */ + KM_TAG_APPLICATION_ID = KM_BYTES | 601, /* Reserved for fugure use -- ignore */ /* * Semantically unenforceable tags, either because they have no specific meaning or because @@ -121,13 +119,10 @@ typedef enum { /* Tags used only to provide data to or receive data from operations */ KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000, /* Used to provide associated data for AEAD modes. */ KM_TAG_NONCE = KM_BYTES | 1001, /* Nonce or Initialization Vector */ - KM_TAG_AEAD_TAG = KM_BYTES | 1002, /* AEAD tag data. Returned from finish() during AEAD - * encryption and provided to begin() during AEAD - * decryption.*/ - KM_TAG_AUTH_TOKEN = KM_BYTES | 1003, /* Authentication token that proves secure user + KM_TAG_AUTH_TOKEN = KM_BYTES | 1002, /* Authentication token that proves secure user authentication has been performed. Structure defined in hw_auth_token_t in hw_auth_token.h. */ - KM_TAG_MAC_LENGTH = KM_INT | 1004, /* MAC or AEAD authentication tag length in bits. */ + KM_TAG_MAC_LENGTH = KM_UINT | 1003, /* MAC or AEAD authentication tag length in bits. */ } keymaster_tag_t; /** @@ -338,7 +333,9 @@ typedef enum { KM_ERROR_MISSING_NONCE = -51, KM_ERROR_INVALID_NONCE = -52, KM_ERROR_MISSING_MAC_LENGTH = -53, + KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54, KM_ERROR_CALLER_NONCE_PROHIBITED = -55, + KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56, KM_ERROR_UNIMPLEMENTED = -100, KM_ERROR_VERSION_MISMATCH = -101, @@ -360,7 +357,7 @@ static inline uint32_t keymaster_tag_mask_type(keymaster_tag_t tag) { static inline bool keymaster_tag_type_repeatable(keymaster_tag_type_t type) { switch (type) { - case KM_INT_REP: + case KM_UINT_REP: case KM_ENUM_REP: return true; default: @@ -443,11 +440,11 @@ inline int keymaster_param_compare(const keymaster_key_param_t* a, const keymast case KM_ENUM: case KM_ENUM_REP: return KEYMASTER_SIMPLE_COMPARE(a->enumerated, b->enumerated); - case KM_INT: - case KM_INT_REP: + case KM_UINT: + case KM_UINT_REP: return KEYMASTER_SIMPLE_COMPARE(a->integer, b->integer); - case KM_LONG: - case KM_LONG_REP: + case KM_ULONG: + case KM_ULONG_REP: return KEYMASTER_SIMPLE_COMPARE(a->long_integer, b->long_integer); case KM_DATE: return KEYMASTER_SIMPLE_COMPARE(a->date_time, b->date_time); diff --git a/include/hardware/sensors.h b/include/hardware/sensors.h index b8b550f..b368ee6 100644 --- a/include/hardware/sensors.h +++ b/include/hardware/sensors.h @@ -108,12 +108,12 @@ enum { */ SENSOR_HAL_NORMAL_MODE = 0, - /* - * Loopback mode. In this mode, the device shall not source data from the + /* + * Data Injection mode. In this mode, the device shall not source data from the * physical sensors as it would in normal mode. Instead sensor data is * injected by the sensor service. */ - SENSOR_HAL_LOOPBACK_MODE = 0x1 + SENSOR_HAL_DATA_INJECTION_MODE = 0x1 }; /* @@ -138,7 +138,16 @@ enum { SENSOR_FLAG_CONTINUOUS_MODE = 0, // 0000 SENSOR_FLAG_ON_CHANGE_MODE = 0x2, // 0010 SENSOR_FLAG_ONE_SHOT_MODE = 0x4, // 0100 - SENSOR_FLAG_SPECIAL_REPORTING_MODE = 0x6 // 0110 + SENSOR_FLAG_SPECIAL_REPORTING_MODE = 0x6, // 0110 + + /* + * Set this flag if the sensor supports data_injection mode and allows data to be injected + * from the SensorService. When in data_injection ONLY sensors with this flag set are injected + * sensor data and only sensors with this flag set are activated. Eg: Accelerometer and Step + * Counter sensors can be set with this flag and SensorService will inject accelerometer data + * and read the corresponding step counts. + */ + SENSOR_FLAG_SUPPORTS_DATA_INJECTION = 0x8 // 1000 }; /* @@ -148,6 +157,12 @@ enum { #define REPORTING_MODE_SHIFT (1) /* + * Mask and shift for data_injection mode sensor flags defined above. + */ +#define DATA_INJECTION_MASK (0x10) +#define DATA_INJECTION_SHIFT (4) + +/* * Sensor type * * Each sensor has a type which defines what this sensor measures and how @@ -838,9 +853,9 @@ struct sensors_module_t { * 0 - Normal operation. Default state of the module. * 1 - Loopback mode. Data is injected for the the supported * sensors by the sensor service in this mode. - * @return 0 on success + * @return 0 on success * -EINVAL if requested mode is not supported - * -EPERM if operation is not allowed + * -EPERM if operation is not allowed */ int (*set_operation_mode)(unsigned int mode); }; @@ -1043,8 +1058,8 @@ typedef struct sensors_poll_device_1 { /* * Inject a single sensor sample to be to this device. * data points to the sensor event to be injected - * @return 0 on success - * -EPERM if operation is not allowed + * @return 0 on success + * -EPERM if operation is not allowed * -EINVAL if sensor event cannot be injected */ int (*inject_sensor_data)(struct sensors_poll_device_1 *dev, const sensors_event_t *data); diff --git a/modules/usbaudio/audio_hal.c b/modules/usbaudio/audio_hal.c index 872fa93..bbea5f5 100644 --- a/modules/usbaudio/audio_hal.c +++ b/modules/usbaudio/audio_hal.c @@ -80,6 +80,7 @@ struct stream_out { struct audio_stream_out stream; pthread_mutex_t lock; /* see note below on mutex acquisition order */ + pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */ bool standby; struct audio_device *dev; /* hardware information - only using this for the lock */ @@ -103,7 +104,8 @@ struct stream_out { struct stream_in { struct audio_stream_in stream; - pthread_mutex_t lock; /* see note below on mutex acquisition order */ + pthread_mutex_t lock; /* see note below on mutex acquisition order */ + pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by capture thread */ bool standby; struct audio_device *dev; /* hardware information - only using this for the lock */ @@ -126,6 +128,13 @@ struct stream_in { }; /* + * NOTE: when multiple mutexes have to be acquired, always take the + * stream_in or stream_out mutex first, followed by the audio_device mutex. + * stream pre_lock is always acquired before stream lock to prevent starvation of control thread by + * higher priority playback or capture thread. + */ + +/* * Extract the card and device numbers from the supplied key/value pairs. * kvpairs A null-terminated string containing the key/value pairs or card and device. * i.e. "card=1;device=42" @@ -203,6 +212,20 @@ static char * device_get_parameters(alsa_device_profile * profile, const char * return result_str; } +void lock_input_stream(struct stream_in *in) +{ + pthread_mutex_lock(&in->pre_lock); + pthread_mutex_lock(&in->lock); + pthread_mutex_unlock(&in->pre_lock); +} + +void lock_output_stream(struct stream_out *out) +{ + pthread_mutex_lock(&out->pre_lock); + pthread_mutex_lock(&out->lock); + pthread_mutex_unlock(&out->pre_lock); +} + /* * HAl Functions */ @@ -260,16 +283,14 @@ static int out_standby(struct audio_stream *stream) { struct stream_out *out = (struct stream_out *)stream; - pthread_mutex_lock(&out->dev->lock); - pthread_mutex_lock(&out->lock); - + lock_output_stream(out); if (!out->standby) { + pthread_mutex_lock(&out->dev->lock); proxy_close(&out->proxy); + pthread_mutex_unlock(&out->dev->lock); out->standby = true; } - pthread_mutex_unlock(&out->lock); - pthread_mutex_unlock(&out->dev->lock); return 0; } @@ -295,9 +316,9 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) return ret_value; } + lock_output_stream(out); /* Lock the device because that is where the profile lives */ pthread_mutex_lock(&out->dev->lock); - pthread_mutex_lock(&out->lock); if (!profile_is_cached_for(out->profile, card, device)) { /* cannot read pcm device info if playback is active */ @@ -316,8 +337,8 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) } } - pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->dev->lock); + pthread_mutex_unlock(&out->lock); return ret_value; } @@ -325,8 +346,8 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) static char * out_get_parameters(const struct audio_stream *stream, const char *keys) { struct stream_out *out = (struct stream_out *)stream; + lock_output_stream(out); pthread_mutex_lock(&out->dev->lock); - pthread_mutex_lock(&out->lock); char * params_str = device_get_parameters(out->profile, keys); @@ -360,17 +381,16 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, si int ret; struct stream_out *out = (struct stream_out *)stream; - pthread_mutex_lock(&out->dev->lock); - pthread_mutex_lock(&out->lock); + lock_output_stream(out); if (out->standby) { + pthread_mutex_lock(&out->dev->lock); ret = start_output_stream(out); + pthread_mutex_unlock(&out->dev->lock); if (ret != 0) { - pthread_mutex_unlock(&out->dev->lock); goto err; } out->standby = false; } - pthread_mutex_unlock(&out->dev->lock); alsa_device_proxy* proxy = &out->proxy; const void * write_buff = buffer; @@ -480,6 +500,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->stream.get_presentation_position = out_get_presentation_position; out->stream.get_next_write_timestamp = out_get_next_write_timestamp; + pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL); + pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL); + out->dev = adev; pthread_mutex_lock(&adev->lock); out->profile = &adev->out_profile; @@ -639,16 +662,15 @@ static int in_standby(struct audio_stream *stream) { struct stream_in *in = (struct stream_in *)stream; - pthread_mutex_lock(&in->dev->lock); - pthread_mutex_lock(&in->lock); - + lock_input_stream(in); if (!in->standby) { + pthread_mutex_lock(&in->dev->lock); proxy_close(&in->proxy); + pthread_mutex_unlock(&in->dev->lock); in->standby = true; } pthread_mutex_unlock(&in->lock); - pthread_mutex_unlock(&in->dev->lock); return 0; } @@ -676,8 +698,8 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) return ret_value; } + lock_input_stream(in); pthread_mutex_lock(&in->dev->lock); - pthread_mutex_lock(&in->lock); if (card >= 0 && device >= 0 && !profile_is_cached_for(in->profile, card, device)) { /* cannot read pcm device info if playback is active */ @@ -696,8 +718,8 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) } } - pthread_mutex_unlock(&in->lock); pthread_mutex_unlock(&in->dev->lock); + pthread_mutex_unlock(&in->lock); return ret_value; } @@ -706,13 +728,13 @@ static char * in_get_parameters(const struct audio_stream *stream, const char *k { struct stream_in *in = (struct stream_in *)stream; + lock_input_stream(in); pthread_mutex_lock(&in->dev->lock); - pthread_mutex_lock(&in->lock); char * params_str = device_get_parameters(in->profile, keys); - pthread_mutex_unlock(&in->lock); pthread_mutex_unlock(&in->dev->lock); + pthread_mutex_unlock(&in->lock); return params_str; } @@ -750,16 +772,16 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t byte struct stream_in * in = (struct stream_in *)stream; - pthread_mutex_lock(&in->dev->lock); - pthread_mutex_lock(&in->lock); + lock_input_stream(in); if (in->standby) { - if (start_input_stream(in) != 0) { - pthread_mutex_unlock(&in->dev->lock); + pthread_mutex_lock(&in->dev->lock); + ret = start_input_stream(in); + pthread_mutex_unlock(&in->dev->lock); + if (ret != 0) { goto err; } in->standby = false; } - pthread_mutex_unlock(&in->dev->lock); alsa_device_profile * profile = in->profile; @@ -858,6 +880,9 @@ static int adev_open_input_stream(struct audio_hw_device *dev, in->stream.read = in_read; in->stream.get_input_frames_lost = in_get_input_frames_lost; + pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL); + pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL); + in->dev = (struct audio_device *)dev; pthread_mutex_lock(&in->dev->lock); |