| /* |
| ** |
| ** Copyright 2009, The Android Open Source Project |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #define LOG_TAG "IAudioPolicyService" |
| #include <utils/Log.h> |
| |
| #include <stdint.h> |
| #include <math.h> |
| #include <sys/types.h> |
| |
| #include <binder/Parcel.h> |
| |
| #include <media/AudioEffect.h> |
| #include <media/IAudioPolicyService.h> |
| |
| #include <system/audio.h> |
| |
| namespace android { |
| |
| enum { |
| SET_DEVICE_CONNECTION_STATE = IBinder::FIRST_CALL_TRANSACTION, |
| GET_DEVICE_CONNECTION_STATE, |
| HANDLE_DEVICE_CONFIG_CHANGE, |
| SET_PHONE_STATE, |
| SET_RINGER_MODE, // reserved, no longer used |
| SET_FORCE_USE, |
| GET_FORCE_USE, |
| GET_OUTPUT, |
| START_OUTPUT, |
| STOP_OUTPUT, |
| RELEASE_OUTPUT, |
| GET_INPUT_FOR_ATTR, |
| START_INPUT, |
| STOP_INPUT, |
| RELEASE_INPUT, |
| INIT_STREAM_VOLUME, |
| SET_STREAM_VOLUME, |
| GET_STREAM_VOLUME, |
| GET_STRATEGY_FOR_STREAM, |
| GET_OUTPUT_FOR_EFFECT, |
| REGISTER_EFFECT, |
| UNREGISTER_EFFECT, |
| IS_STREAM_ACTIVE, |
| IS_SOURCE_ACTIVE, |
| GET_DEVICES_FOR_STREAM, |
| QUERY_DEFAULT_PRE_PROCESSING, |
| SET_EFFECT_ENABLED, |
| IS_STREAM_ACTIVE_REMOTELY, |
| IS_OFFLOAD_SUPPORTED, |
| LIST_AUDIO_PORTS, |
| GET_AUDIO_PORT, |
| CREATE_AUDIO_PATCH, |
| RELEASE_AUDIO_PATCH, |
| LIST_AUDIO_PATCHES, |
| SET_AUDIO_PORT_CONFIG, |
| REGISTER_CLIENT, |
| GET_OUTPUT_FOR_ATTR, |
| ACQUIRE_SOUNDTRIGGER_SESSION, |
| RELEASE_SOUNDTRIGGER_SESSION, |
| GET_PHONE_STATE, |
| REGISTER_POLICY_MIXES, |
| START_AUDIO_SOURCE, |
| STOP_AUDIO_SOURCE, |
| SET_AUDIO_PORT_CALLBACK_ENABLED, |
| SET_MASTER_MONO, |
| GET_MASTER_MONO, |
| GET_STREAM_VOLUME_DB |
| }; |
| |
| #define MAX_ITEMS_PER_LIST 1024 |
| |
| class BpAudioPolicyService : public BpInterface<IAudioPolicyService> |
| { |
| public: |
| explicit BpAudioPolicyService(const sp<IBinder>& impl) |
| : BpInterface<IAudioPolicyService>(impl) |
| { |
| } |
| |
| virtual status_t setDeviceConnectionState( |
| audio_devices_t device, |
| audio_policy_dev_state_t state, |
| const char *device_address, |
| const char *device_name) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(device)); |
| data.writeInt32(static_cast <uint32_t>(state)); |
| data.writeCString(device_address); |
| data.writeCString(device_name); |
| remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual audio_policy_dev_state_t getDeviceConnectionState( |
| audio_devices_t device, |
| const char *device_address) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(device)); |
| data.writeCString(device_address); |
| remote()->transact(GET_DEVICE_CONNECTION_STATE, data, &reply); |
| return static_cast <audio_policy_dev_state_t>(reply.readInt32()); |
| } |
| |
| virtual status_t handleDeviceConfigChange(audio_devices_t device, |
| const char *device_address, |
| const char *device_name) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(device)); |
| data.writeCString(device_address); |
| data.writeCString(device_name); |
| remote()->transact(HANDLE_DEVICE_CONFIG_CHANGE, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual status_t setPhoneState(audio_mode_t state) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(state); |
| remote()->transact(SET_PHONE_STATE, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(usage)); |
| data.writeInt32(static_cast <uint32_t>(config)); |
| remote()->transact(SET_FORCE_USE, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(usage)); |
| remote()->transact(GET_FORCE_USE, data, &reply); |
| return static_cast <audio_policy_forced_cfg_t> (reply.readInt32()); |
| } |
| |
| virtual audio_io_handle_t getOutput( |
| audio_stream_type_t stream, |
| uint32_t samplingRate, |
| audio_format_t format, |
| audio_channel_mask_t channelMask, |
| audio_output_flags_t flags, |
| const audio_offload_info_t *offloadInfo) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(stream)); |
| data.writeInt32(samplingRate); |
| data.writeInt32(static_cast <uint32_t>(format)); |
| data.writeInt32(channelMask); |
| data.writeInt32(static_cast <uint32_t>(flags)); |
| // hasOffloadInfo |
| if (offloadInfo == NULL) { |
| data.writeInt32(0); |
| } else { |
| data.writeInt32(1); |
| data.write(offloadInfo, sizeof(audio_offload_info_t)); |
| } |
| remote()->transact(GET_OUTPUT, data, &reply); |
| return static_cast <audio_io_handle_t> (reply.readInt32()); |
| } |
| |
| virtual status_t getOutputForAttr(const audio_attributes_t *attr, |
| audio_io_handle_t *output, |
| audio_session_t session, |
| audio_stream_type_t *stream, |
| uid_t uid, |
| const audio_config_t *config, |
| audio_output_flags_t flags, |
| audio_port_handle_t *selectedDeviceId, |
| audio_port_handle_t *portId) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| if (attr == NULL) { |
| if (stream == NULL) { |
| ALOGE("getOutputForAttr(): NULL audio attributes and stream type"); |
| return BAD_VALUE; |
| } |
| if (*stream == AUDIO_STREAM_DEFAULT) { |
| ALOGE("getOutputForAttr unspecified stream type"); |
| return BAD_VALUE; |
| } |
| } |
| if (output == NULL) { |
| ALOGE("getOutputForAttr NULL output - shouldn't happen"); |
| return BAD_VALUE; |
| } |
| if (selectedDeviceId == NULL) { |
| ALOGE("getOutputForAttr NULL selectedDeviceId - shouldn't happen"); |
| return BAD_VALUE; |
| } |
| if (portId == NULL) { |
| ALOGE("getOutputForAttr NULL portId - shouldn't happen"); |
| return BAD_VALUE; |
| } |
| if (attr == NULL) { |
| data.writeInt32(0); |
| } else { |
| data.writeInt32(1); |
| data.write(attr, sizeof(audio_attributes_t)); |
| } |
| data.writeInt32(session); |
| if (stream == NULL) { |
| data.writeInt32(0); |
| } else { |
| data.writeInt32(1); |
| data.writeInt32(*stream); |
| } |
| data.writeInt32(uid); |
| data.write(config, sizeof(audio_config_t)); |
| data.writeInt32(static_cast <uint32_t>(flags)); |
| data.writeInt32(*selectedDeviceId); |
| data.writeInt32(*portId); |
| status_t status = remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| status = (status_t)reply.readInt32(); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| *output = (audio_io_handle_t)reply.readInt32(); |
| audio_stream_type_t lStream = (audio_stream_type_t)reply.readInt32(); |
| if (stream != NULL) { |
| *stream = lStream; |
| } |
| *selectedDeviceId = (audio_port_handle_t)reply.readInt32(); |
| *portId = (audio_port_handle_t)reply.readInt32(); |
| return status; |
| } |
| |
| virtual status_t startOutput(audio_io_handle_t output, |
| audio_stream_type_t stream, |
| audio_session_t session) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(output); |
| data.writeInt32((int32_t) stream); |
| data.writeInt32((int32_t) session); |
| remote()->transact(START_OUTPUT, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual status_t stopOutput(audio_io_handle_t output, |
| audio_stream_type_t stream, |
| audio_session_t session) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(output); |
| data.writeInt32((int32_t) stream); |
| data.writeInt32((int32_t) session); |
| remote()->transact(STOP_OUTPUT, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual void releaseOutput(audio_io_handle_t output, |
| audio_stream_type_t stream, |
| audio_session_t session) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(output); |
| data.writeInt32((int32_t)stream); |
| data.writeInt32((int32_t)session); |
| remote()->transact(RELEASE_OUTPUT, data, &reply); |
| } |
| |
| virtual status_t getInputForAttr(const audio_attributes_t *attr, |
| audio_io_handle_t *input, |
| audio_session_t session, |
| pid_t pid, |
| uid_t uid, |
| const audio_config_base_t *config, |
| audio_input_flags_t flags, |
| audio_port_handle_t *selectedDeviceId, |
| audio_port_handle_t *portId) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| if (attr == NULL) { |
| ALOGE("getInputForAttr NULL attr - shouldn't happen"); |
| return BAD_VALUE; |
| } |
| if (input == NULL) { |
| ALOGE("getInputForAttr NULL input - shouldn't happen"); |
| return BAD_VALUE; |
| } |
| if (selectedDeviceId == NULL) { |
| ALOGE("getInputForAttr NULL selectedDeviceId - shouldn't happen"); |
| return BAD_VALUE; |
| } |
| if (portId == NULL) { |
| ALOGE("getInputForAttr NULL portId - shouldn't happen"); |
| return BAD_VALUE; |
| } |
| data.write(attr, sizeof(audio_attributes_t)); |
| data.writeInt32(*input); |
| data.writeInt32(session); |
| data.writeInt32(pid); |
| data.writeInt32(uid); |
| data.write(config, sizeof(audio_config_base_t)); |
| data.writeInt32(flags); |
| data.writeInt32(*selectedDeviceId); |
| data.writeInt32(*portId); |
| status_t status = remote()->transact(GET_INPUT_FOR_ATTR, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| status = reply.readInt32(); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| *input = (audio_io_handle_t)reply.readInt32(); |
| *selectedDeviceId = (audio_port_handle_t)reply.readInt32(); |
| *portId = (audio_port_handle_t)reply.readInt32(); |
| return NO_ERROR; |
| } |
| |
| virtual status_t startInput(audio_io_handle_t input, |
| audio_session_t session) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(input); |
| data.writeInt32(session); |
| remote()->transact(START_INPUT, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual status_t stopInput(audio_io_handle_t input, |
| audio_session_t session) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(input); |
| data.writeInt32(session); |
| remote()->transact(STOP_INPUT, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual void releaseInput(audio_io_handle_t input, |
| audio_session_t session) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(input); |
| data.writeInt32(session); |
| remote()->transact(RELEASE_INPUT, data, &reply); |
| } |
| |
| virtual status_t initStreamVolume(audio_stream_type_t stream, |
| int indexMin, |
| int indexMax) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(stream)); |
| data.writeInt32(indexMin); |
| data.writeInt32(indexMax); |
| remote()->transact(INIT_STREAM_VOLUME, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual status_t setStreamVolumeIndex(audio_stream_type_t stream, |
| int index, |
| audio_devices_t device) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(stream)); |
| data.writeInt32(index); |
| data.writeInt32(static_cast <uint32_t>(device)); |
| remote()->transact(SET_STREAM_VOLUME, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual status_t getStreamVolumeIndex(audio_stream_type_t stream, |
| int *index, |
| audio_devices_t device) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(stream)); |
| data.writeInt32(static_cast <uint32_t>(device)); |
| |
| remote()->transact(GET_STREAM_VOLUME, data, &reply); |
| int lIndex = reply.readInt32(); |
| if (index) *index = lIndex; |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual uint32_t getStrategyForStream(audio_stream_type_t stream) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(stream)); |
| remote()->transact(GET_STRATEGY_FOR_STREAM, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <uint32_t>(stream)); |
| remote()->transact(GET_DEVICES_FOR_STREAM, data, &reply); |
| return (audio_devices_t) reply.readInt32(); |
| } |
| |
| virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.write(desc, sizeof(effect_descriptor_t)); |
| remote()->transact(GET_OUTPUT_FOR_EFFECT, data, &reply); |
| return static_cast <audio_io_handle_t> (reply.readInt32()); |
| } |
| |
| virtual status_t registerEffect(const effect_descriptor_t *desc, |
| audio_io_handle_t io, |
| uint32_t strategy, |
| audio_session_t session, |
| int id) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.write(desc, sizeof(effect_descriptor_t)); |
| data.writeInt32(io); |
| data.writeInt32(strategy); |
| data.writeInt32(session); |
| data.writeInt32(id); |
| remote()->transact(REGISTER_EFFECT, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual status_t unregisterEffect(int id) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(id); |
| remote()->transact(UNREGISTER_EFFECT, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual status_t setEffectEnabled(int id, bool enabled) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(id); |
| data.writeInt32(enabled); |
| remote()->transact(SET_EFFECT_ENABLED, data, &reply); |
| return static_cast <status_t> (reply.readInt32()); |
| } |
| |
| virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32((int32_t) stream); |
| data.writeInt32(inPastMs); |
| remote()->transact(IS_STREAM_ACTIVE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32((int32_t) stream); |
| data.writeInt32(inPastMs); |
| remote()->transact(IS_STREAM_ACTIVE_REMOTELY, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| virtual bool isSourceActive(audio_source_t source) const |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32((int32_t) source); |
| remote()->transact(IS_SOURCE_ACTIVE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| virtual status_t queryDefaultPreProcessing(audio_session_t audioSession, |
| effect_descriptor_t *descriptors, |
| uint32_t *count) |
| { |
| if (descriptors == NULL || count == NULL) { |
| return BAD_VALUE; |
| } |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(audioSession); |
| data.writeInt32(*count); |
| status_t status = remote()->transact(QUERY_DEFAULT_PRE_PROCESSING, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| status = static_cast <status_t> (reply.readInt32()); |
| uint32_t retCount = reply.readInt32(); |
| if (retCount != 0) { |
| uint32_t numDesc = (retCount < *count) ? retCount : *count; |
| reply.read(descriptors, sizeof(effect_descriptor_t) * numDesc); |
| } |
| *count = retCount; |
| return status; |
| } |
| |
| virtual bool isOffloadSupported(const audio_offload_info_t& info) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.write(&info, sizeof(audio_offload_info_t)); |
| remote()->transact(IS_OFFLOAD_SUPPORTED, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| virtual status_t listAudioPorts(audio_port_role_t role, |
| audio_port_type_t type, |
| unsigned int *num_ports, |
| struct audio_port *ports, |
| unsigned int *generation) |
| { |
| if (num_ports == NULL || (*num_ports != 0 && ports == NULL) || |
| generation == NULL) { |
| return BAD_VALUE; |
| } |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| unsigned int numPortsReq = (ports == NULL) ? 0 : *num_ports; |
| data.writeInt32(role); |
| data.writeInt32(type); |
| data.writeInt32(numPortsReq); |
| status_t status = remote()->transact(LIST_AUDIO_PORTS, data, &reply); |
| if (status == NO_ERROR) { |
| status = (status_t)reply.readInt32(); |
| *num_ports = (unsigned int)reply.readInt32(); |
| } |
| if (status == NO_ERROR) { |
| if (numPortsReq > *num_ports) { |
| numPortsReq = *num_ports; |
| } |
| if (numPortsReq > 0) { |
| reply.read(ports, numPortsReq * sizeof(struct audio_port)); |
| } |
| *generation = reply.readInt32(); |
| } |
| return status; |
| } |
| |
| virtual status_t getAudioPort(struct audio_port *port) |
| { |
| if (port == NULL) { |
| return BAD_VALUE; |
| } |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.write(port, sizeof(struct audio_port)); |
| status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply); |
| if (status != NO_ERROR || |
| (status = (status_t)reply.readInt32()) != NO_ERROR) { |
| return status; |
| } |
| reply.read(port, sizeof(struct audio_port)); |
| return status; |
| } |
| |
| virtual status_t createAudioPatch(const struct audio_patch *patch, |
| audio_patch_handle_t *handle) |
| { |
| if (patch == NULL || handle == NULL) { |
| return BAD_VALUE; |
| } |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.write(patch, sizeof(struct audio_patch)); |
| data.write(handle, sizeof(audio_patch_handle_t)); |
| status_t status = remote()->transact(CREATE_AUDIO_PATCH, data, &reply); |
| if (status != NO_ERROR || |
| (status = (status_t)reply.readInt32()) != NO_ERROR) { |
| return status; |
| } |
| reply.read(handle, sizeof(audio_patch_handle_t)); |
| return status; |
| } |
| |
| virtual status_t releaseAudioPatch(audio_patch_handle_t handle) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.write(&handle, sizeof(audio_patch_handle_t)); |
| status_t status = remote()->transact(RELEASE_AUDIO_PATCH, data, &reply); |
| if (status != NO_ERROR) { |
| status = (status_t)reply.readInt32(); |
| } |
| return status; |
| } |
| |
| virtual status_t listAudioPatches(unsigned int *num_patches, |
| struct audio_patch *patches, |
| unsigned int *generation) |
| { |
| if (num_patches == NULL || (*num_patches != 0 && patches == NULL) || |
| generation == NULL) { |
| return BAD_VALUE; |
| } |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| unsigned int numPatchesReq = (patches == NULL) ? 0 : *num_patches; |
| data.writeInt32(numPatchesReq); |
| status_t status = remote()->transact(LIST_AUDIO_PATCHES, data, &reply); |
| if (status == NO_ERROR) { |
| status = (status_t)reply.readInt32(); |
| *num_patches = (unsigned int)reply.readInt32(); |
| } |
| if (status == NO_ERROR) { |
| if (numPatchesReq > *num_patches) { |
| numPatchesReq = *num_patches; |
| } |
| if (numPatchesReq > 0) { |
| reply.read(patches, numPatchesReq * sizeof(struct audio_patch)); |
| } |
| *generation = reply.readInt32(); |
| } |
| return status; |
| } |
| |
| virtual status_t setAudioPortConfig(const struct audio_port_config *config) |
| { |
| if (config == NULL) { |
| return BAD_VALUE; |
| } |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.write(config, sizeof(struct audio_port_config)); |
| status_t status = remote()->transact(SET_AUDIO_PORT_CONFIG, data, &reply); |
| if (status != NO_ERROR) { |
| status = (status_t)reply.readInt32(); |
| } |
| return status; |
| } |
| |
| virtual void registerClient(const sp<IAudioPolicyServiceClient>& client) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeStrongBinder(IInterface::asBinder(client)); |
| remote()->transact(REGISTER_CLIENT, data, &reply); |
| } |
| |
| virtual void setAudioPortCallbacksEnabled(bool enabled) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(enabled ? 1 : 0); |
| remote()->transact(SET_AUDIO_PORT_CALLBACK_ENABLED, data, &reply); |
| } |
| |
| virtual status_t acquireSoundTriggerSession(audio_session_t *session, |
| audio_io_handle_t *ioHandle, |
| audio_devices_t *device) |
| { |
| if (session == NULL || ioHandle == NULL || device == NULL) { |
| return BAD_VALUE; |
| } |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| status_t status = remote()->transact(ACQUIRE_SOUNDTRIGGER_SESSION, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| status = (status_t)reply.readInt32(); |
| if (status == NO_ERROR) { |
| *session = (audio_session_t)reply.readInt32(); |
| *ioHandle = (audio_io_handle_t)reply.readInt32(); |
| *device = (audio_devices_t)reply.readInt32(); |
| } |
| return status; |
| } |
| |
| virtual status_t releaseSoundTriggerSession(audio_session_t session) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(session); |
| status_t status = remote()->transact(RELEASE_SOUNDTRIGGER_SESSION, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| return (status_t)reply.readInt32(); |
| } |
| |
| virtual audio_mode_t getPhoneState() |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| status_t status = remote()->transact(GET_PHONE_STATE, data, &reply); |
| if (status != NO_ERROR) { |
| return AUDIO_MODE_INVALID; |
| } |
| return (audio_mode_t)reply.readInt32(); |
| } |
| |
| virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(registration ? 1 : 0); |
| size_t size = mixes.size(); |
| if (size > MAX_MIXES_PER_POLICY) { |
| size = MAX_MIXES_PER_POLICY; |
| } |
| size_t sizePosition = data.dataPosition(); |
| data.writeInt32(size); |
| size_t finalSize = size; |
| for (size_t i = 0; i < size; i++) { |
| size_t position = data.dataPosition(); |
| if (mixes[i].writeToParcel(&data) != NO_ERROR) { |
| data.setDataPosition(position); |
| finalSize--; |
| } |
| } |
| if (size != finalSize) { |
| size_t position = data.dataPosition(); |
| data.setDataPosition(sizePosition); |
| data.writeInt32(finalSize); |
| data.setDataPosition(position); |
| } |
| status_t status = remote()->transact(REGISTER_POLICY_MIXES, data, &reply); |
| if (status == NO_ERROR) { |
| status = (status_t)reply.readInt32(); |
| } |
| return status; |
| } |
| |
| virtual status_t startAudioSource(const struct audio_port_config *source, |
| const audio_attributes_t *attributes, |
| audio_patch_handle_t *handle) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| if (source == NULL || attributes == NULL || handle == NULL) { |
| return BAD_VALUE; |
| } |
| data.write(source, sizeof(struct audio_port_config)); |
| data.write(attributes, sizeof(audio_attributes_t)); |
| status_t status = remote()->transact(START_AUDIO_SOURCE, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| status = (status_t)reply.readInt32(); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| *handle = (audio_patch_handle_t)reply.readInt32(); |
| return status; |
| } |
| |
| virtual status_t stopAudioSource(audio_patch_handle_t handle) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(handle); |
| status_t status = remote()->transact(STOP_AUDIO_SOURCE, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| status = (status_t)reply.readInt32(); |
| return status; |
| } |
| |
| virtual status_t setMasterMono(bool mono) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast<int32_t>(mono)); |
| status_t status = remote()->transact(SET_MASTER_MONO, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| return static_cast<status_t>(reply.readInt32()); |
| } |
| |
| virtual status_t getMasterMono(bool *mono) |
| { |
| if (mono == nullptr) { |
| return BAD_VALUE; |
| } |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| |
| status_t status = remote()->transact(GET_MASTER_MONO, data, &reply); |
| if (status != NO_ERROR) { |
| return status; |
| } |
| status = static_cast<status_t>(reply.readInt32()); |
| if (status == NO_ERROR) { |
| *mono = static_cast<bool>(reply.readInt32()); |
| } |
| return status; |
| } |
| |
| virtual float getStreamVolumeDB(audio_stream_type_t stream, int index, audio_devices_t device) |
| { |
| Parcel data, reply; |
| data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); |
| data.writeInt32(static_cast <int32_t>(stream)); |
| data.writeInt32(static_cast <int32_t>(index)); |
| data.writeUint32(static_cast <uint32_t>(device)); |
| status_t status = remote()->transact(GET_STREAM_VOLUME_DB, data, &reply); |
| if (status != NO_ERROR) { |
| return NAN; |
| } |
| return reply.readFloat(); |
| } |
| }; |
| |
| IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); |
| |
| // ---------------------------------------------------------------------- |
| |
| |
| status_t BnAudioPolicyService::onTransact( |
| uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) |
| { |
| switch (code) { |
| case SET_DEVICE_CONNECTION_STATE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_devices_t device = |
| static_cast <audio_devices_t>(data.readInt32()); |
| audio_policy_dev_state_t state = |
| static_cast <audio_policy_dev_state_t>(data.readInt32()); |
| const char *device_address = data.readCString(); |
| const char *device_name = data.readCString(); |
| if (device_address == nullptr || device_name == nullptr) { |
| ALOGE("Bad Binder transaction: SET_DEVICE_CONNECTION_STATE for device %u", device); |
| reply->writeInt32(static_cast<int32_t> (BAD_VALUE)); |
| } else { |
| reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device, |
| state, |
| device_address, |
| device_name))); |
| } |
| return NO_ERROR; |
| } break; |
| |
| case GET_DEVICE_CONNECTION_STATE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_devices_t device = |
| static_cast<audio_devices_t> (data.readInt32()); |
| const char *device_address = data.readCString(); |
| if (device_address == nullptr) { |
| ALOGE("Bad Binder transaction: GET_DEVICE_CONNECTION_STATE for device %u", device); |
| reply->writeInt32(static_cast<int32_t> (AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)); |
| } else { |
| reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device, |
| device_address))); |
| } |
| return NO_ERROR; |
| } break; |
| |
| case HANDLE_DEVICE_CONFIG_CHANGE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_devices_t device = |
| static_cast <audio_devices_t>(data.readInt32()); |
| const char *device_address = data.readCString(); |
| const char *device_name = data.readCString(); |
| if (device_address == nullptr || device_name == nullptr) { |
| ALOGE("Bad Binder transaction: HANDLE_DEVICE_CONFIG_CHANGE for device %u", device); |
| reply->writeInt32(static_cast<int32_t> (BAD_VALUE)); |
| } else { |
| reply->writeInt32(static_cast<uint32_t> (handleDeviceConfigChange(device, |
| device_address, |
| device_name))); |
| } |
| return NO_ERROR; |
| } break; |
| |
| case SET_PHONE_STATE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| reply->writeInt32(static_cast <uint32_t>(setPhoneState( |
| (audio_mode_t) data.readInt32()))); |
| return NO_ERROR; |
| } break; |
| |
| case SET_FORCE_USE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_policy_force_use_t usage = static_cast <audio_policy_force_use_t>( |
| data.readInt32()); |
| audio_policy_forced_cfg_t config = |
| static_cast <audio_policy_forced_cfg_t>(data.readInt32()); |
| reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config))); |
| return NO_ERROR; |
| } break; |
| |
| case GET_FORCE_USE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_policy_force_use_t usage = static_cast <audio_policy_force_use_t>( |
| data.readInt32()); |
| reply->writeInt32(static_cast <uint32_t>(getForceUse(usage))); |
| return NO_ERROR; |
| } break; |
| |
| case GET_OUTPUT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| uint32_t samplingRate = data.readInt32(); |
| audio_format_t format = (audio_format_t) data.readInt32(); |
| audio_channel_mask_t channelMask = data.readInt32(); |
| audio_output_flags_t flags = |
| static_cast <audio_output_flags_t>(data.readInt32()); |
| bool hasOffloadInfo = data.readInt32() != 0; |
| audio_offload_info_t offloadInfo; |
| if (hasOffloadInfo) { |
| data.read(&offloadInfo, sizeof(audio_offload_info_t)); |
| } |
| audio_io_handle_t output = getOutput(stream, |
| samplingRate, |
| format, |
| channelMask, |
| flags, |
| hasOffloadInfo ? &offloadInfo : NULL); |
| reply->writeInt32(static_cast <int>(output)); |
| return NO_ERROR; |
| } break; |
| |
| case GET_OUTPUT_FOR_ATTR: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_attributes_t attr; |
| bool hasAttributes = data.readInt32() != 0; |
| if (hasAttributes) { |
| data.read(&attr, sizeof(audio_attributes_t)); |
| sanetizeAudioAttributes(&attr); |
| } |
| audio_session_t session = (audio_session_t)data.readInt32(); |
| audio_stream_type_t stream = AUDIO_STREAM_DEFAULT; |
| bool hasStream = data.readInt32() != 0; |
| if (hasStream) { |
| stream = (audio_stream_type_t)data.readInt32(); |
| } |
| uid_t uid = (uid_t)data.readInt32(); |
| audio_config_t config; |
| memset(&config, 0, sizeof(audio_config_t)); |
| data.read(&config, sizeof(audio_config_t)); |
| audio_output_flags_t flags = |
| static_cast <audio_output_flags_t>(data.readInt32()); |
| audio_port_handle_t selectedDeviceId = data.readInt32(); |
| audio_port_handle_t portId = (audio_port_handle_t)data.readInt32(); |
| audio_io_handle_t output = 0; |
| status_t status = getOutputForAttr(hasAttributes ? &attr : NULL, |
| &output, session, &stream, uid, |
| &config, |
| flags, &selectedDeviceId, &portId); |
| reply->writeInt32(status); |
| reply->writeInt32(output); |
| reply->writeInt32(stream); |
| reply->writeInt32(selectedDeviceId); |
| reply->writeInt32(portId); |
| return NO_ERROR; |
| } break; |
| |
| case START_OUTPUT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32()); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| audio_session_t session = (audio_session_t)data.readInt32(); |
| reply->writeInt32(static_cast <uint32_t>(startOutput(output, |
| stream, |
| session))); |
| return NO_ERROR; |
| } break; |
| |
| case STOP_OUTPUT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32()); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| audio_session_t session = (audio_session_t)data.readInt32(); |
| reply->writeInt32(static_cast <uint32_t>(stopOutput(output, |
| stream, |
| session))); |
| return NO_ERROR; |
| } break; |
| |
| case RELEASE_OUTPUT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32()); |
| audio_stream_type_t stream = (audio_stream_type_t)data.readInt32(); |
| audio_session_t session = (audio_session_t)data.readInt32(); |
| releaseOutput(output, stream, session); |
| return NO_ERROR; |
| } break; |
| |
| case GET_INPUT_FOR_ATTR: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_attributes_t attr; |
| data.read(&attr, sizeof(audio_attributes_t)); |
| sanetizeAudioAttributes(&attr); |
| audio_io_handle_t input = (audio_io_handle_t)data.readInt32(); |
| audio_session_t session = (audio_session_t)data.readInt32(); |
| pid_t pid = (pid_t)data.readInt32(); |
| uid_t uid = (uid_t)data.readInt32(); |
| audio_config_base_t config; |
| memset(&config, 0, sizeof(audio_config_base_t)); |
| data.read(&config, sizeof(audio_config_base_t)); |
| audio_input_flags_t flags = (audio_input_flags_t) data.readInt32(); |
| audio_port_handle_t selectedDeviceId = (audio_port_handle_t) data.readInt32(); |
| audio_port_handle_t portId = (audio_port_handle_t)data.readInt32(); |
| status_t status = getInputForAttr(&attr, &input, session, pid, uid, |
| &config, |
| flags, &selectedDeviceId, &portId); |
| reply->writeInt32(status); |
| if (status == NO_ERROR) { |
| reply->writeInt32(input); |
| reply->writeInt32(selectedDeviceId); |
| reply->writeInt32(portId); |
| } |
| return NO_ERROR; |
| } break; |
| |
| case START_INPUT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32()); |
| audio_session_t session = static_cast <audio_session_t>(data.readInt32()); |
| reply->writeInt32(static_cast <uint32_t>(startInput(input, session))); |
| return NO_ERROR; |
| } break; |
| |
| case STOP_INPUT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32()); |
| audio_session_t session = static_cast <audio_session_t>(data.readInt32()); |
| reply->writeInt32(static_cast <uint32_t>(stopInput(input, session))); |
| return NO_ERROR; |
| } break; |
| |
| case RELEASE_INPUT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32()); |
| audio_session_t session = static_cast <audio_session_t>(data.readInt32()); |
| releaseInput(input, session); |
| return NO_ERROR; |
| } break; |
| |
| case INIT_STREAM_VOLUME: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| int indexMin = data.readInt32(); |
| int indexMax = data.readInt32(); |
| reply->writeInt32(static_cast <uint32_t>(initStreamVolume(stream, indexMin,indexMax))); |
| return NO_ERROR; |
| } break; |
| |
| case SET_STREAM_VOLUME: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| int index = data.readInt32(); |
| audio_devices_t device = static_cast <audio_devices_t>(data.readInt32()); |
| reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, |
| index, |
| device))); |
| return NO_ERROR; |
| } break; |
| |
| case GET_STREAM_VOLUME: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| audio_devices_t device = static_cast <audio_devices_t>(data.readInt32()); |
| int index = 0; |
| status_t status = getStreamVolumeIndex(stream, &index, device); |
| reply->writeInt32(index); |
| reply->writeInt32(static_cast <uint32_t>(status)); |
| return NO_ERROR; |
| } break; |
| |
| case GET_STRATEGY_FOR_STREAM: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| reply->writeInt32(getStrategyForStream(stream)); |
| return NO_ERROR; |
| } break; |
| |
| case GET_DEVICES_FOR_STREAM: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| reply->writeInt32(static_cast <int>(getDevicesForStream(stream))); |
| return NO_ERROR; |
| } break; |
| |
| case GET_OUTPUT_FOR_EFFECT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| effect_descriptor_t desc; |
| data.read(&desc, sizeof(effect_descriptor_t)); |
| audio_io_handle_t output = getOutputForEffect(&desc); |
| reply->writeInt32(static_cast <int>(output)); |
| return NO_ERROR; |
| } break; |
| |
| case REGISTER_EFFECT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| effect_descriptor_t desc; |
| data.read(&desc, sizeof(effect_descriptor_t)); |
| audio_io_handle_t io = data.readInt32(); |
| uint32_t strategy = data.readInt32(); |
| audio_session_t session = (audio_session_t) data.readInt32(); |
| int id = data.readInt32(); |
| reply->writeInt32(static_cast <int32_t>(registerEffect(&desc, |
| io, |
| strategy, |
| session, |
| id))); |
| return NO_ERROR; |
| } break; |
| |
| case UNREGISTER_EFFECT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| int id = data.readInt32(); |
| reply->writeInt32(static_cast <int32_t>(unregisterEffect(id))); |
| return NO_ERROR; |
| } break; |
| |
| case SET_EFFECT_ENABLED: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| int id = data.readInt32(); |
| bool enabled = static_cast <bool>(data.readInt32()); |
| reply->writeInt32(static_cast <int32_t>(setEffectEnabled(id, enabled))); |
| return NO_ERROR; |
| } break; |
| |
| case IS_STREAM_ACTIVE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = (audio_stream_type_t) data.readInt32(); |
| uint32_t inPastMs = (uint32_t)data.readInt32(); |
| reply->writeInt32( isStreamActive(stream, inPastMs) ); |
| return NO_ERROR; |
| } break; |
| |
| case IS_STREAM_ACTIVE_REMOTELY: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = (audio_stream_type_t) data.readInt32(); |
| uint32_t inPastMs = (uint32_t)data.readInt32(); |
| reply->writeInt32( isStreamActiveRemotely(stream, inPastMs) ); |
| return NO_ERROR; |
| } break; |
| |
| case IS_SOURCE_ACTIVE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_source_t source = (audio_source_t) data.readInt32(); |
| reply->writeInt32( isSourceActive(source)); |
| return NO_ERROR; |
| } |
| |
| case QUERY_DEFAULT_PRE_PROCESSING: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_session_t audioSession = (audio_session_t) data.readInt32(); |
| uint32_t count = data.readInt32(); |
| if (count > AudioEffect::kMaxPreProcessing) { |
| count = AudioEffect::kMaxPreProcessing; |
| } |
| uint32_t retCount = count; |
| effect_descriptor_t *descriptors = new effect_descriptor_t[count]; |
| status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount); |
| reply->writeInt32(status); |
| if (status != NO_ERROR && status != NO_MEMORY) { |
| retCount = 0; |
| } |
| reply->writeInt32(retCount); |
| if (retCount != 0) { |
| if (retCount < count) { |
| count = retCount; |
| } |
| reply->write(descriptors, sizeof(effect_descriptor_t) * count); |
| } |
| delete[] descriptors; |
| return status; |
| } |
| |
| case IS_OFFLOAD_SUPPORTED: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_offload_info_t info; |
| data.read(&info, sizeof(audio_offload_info_t)); |
| bool isSupported = isOffloadSupported(info); |
| reply->writeInt32(isSupported); |
| return NO_ERROR; |
| } |
| |
| case LIST_AUDIO_PORTS: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_port_role_t role = (audio_port_role_t)data.readInt32(); |
| audio_port_type_t type = (audio_port_type_t)data.readInt32(); |
| unsigned int numPortsReq = data.readInt32(); |
| if (numPortsReq > MAX_ITEMS_PER_LIST) { |
| numPortsReq = MAX_ITEMS_PER_LIST; |
| } |
| unsigned int numPorts = numPortsReq; |
| struct audio_port *ports = |
| (struct audio_port *)calloc(numPortsReq, sizeof(struct audio_port)); |
| if (ports == NULL) { |
| reply->writeInt32(NO_MEMORY); |
| reply->writeInt32(0); |
| return NO_ERROR; |
| } |
| unsigned int generation; |
| status_t status = listAudioPorts(role, type, &numPorts, ports, &generation); |
| reply->writeInt32(status); |
| reply->writeInt32(numPorts); |
| |
| if (status == NO_ERROR) { |
| if (numPortsReq > numPorts) { |
| numPortsReq = numPorts; |
| } |
| reply->write(ports, numPortsReq * sizeof(struct audio_port)); |
| reply->writeInt32(generation); |
| } |
| free(ports); |
| return NO_ERROR; |
| } |
| |
| case GET_AUDIO_PORT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| struct audio_port port = {}; |
| if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) { |
| ALOGE("b/23912202"); |
| } |
| status_t status = getAudioPort(&port); |
| reply->writeInt32(status); |
| if (status == NO_ERROR) { |
| reply->write(&port, sizeof(struct audio_port)); |
| } |
| return NO_ERROR; |
| } |
| |
| case CREATE_AUDIO_PATCH: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| struct audio_patch patch; |
| data.read(&patch, sizeof(struct audio_patch)); |
| audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE; |
| if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) { |
| ALOGE("b/23912202"); |
| } |
| status_t status = createAudioPatch(&patch, &handle); |
| reply->writeInt32(status); |
| if (status == NO_ERROR) { |
| reply->write(&handle, sizeof(audio_patch_handle_t)); |
| } |
| return NO_ERROR; |
| } |
| |
| case RELEASE_AUDIO_PATCH: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_patch_handle_t handle; |
| data.read(&handle, sizeof(audio_patch_handle_t)); |
| status_t status = releaseAudioPatch(handle); |
| reply->writeInt32(status); |
| return NO_ERROR; |
| } |
| |
| case LIST_AUDIO_PATCHES: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| unsigned int numPatchesReq = data.readInt32(); |
| if (numPatchesReq > MAX_ITEMS_PER_LIST) { |
| numPatchesReq = MAX_ITEMS_PER_LIST; |
| } |
| unsigned int numPatches = numPatchesReq; |
| struct audio_patch *patches = |
| (struct audio_patch *)calloc(numPatchesReq, |
| sizeof(struct audio_patch)); |
| if (patches == NULL) { |
| reply->writeInt32(NO_MEMORY); |
| reply->writeInt32(0); |
| return NO_ERROR; |
| } |
| unsigned int generation; |
| status_t status = listAudioPatches(&numPatches, patches, &generation); |
| reply->writeInt32(status); |
| reply->writeInt32(numPatches); |
| if (status == NO_ERROR) { |
| if (numPatchesReq > numPatches) { |
| numPatchesReq = numPatches; |
| } |
| reply->write(patches, numPatchesReq * sizeof(struct audio_patch)); |
| reply->writeInt32(generation); |
| } |
| free(patches); |
| return NO_ERROR; |
| } |
| |
| case SET_AUDIO_PORT_CONFIG: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| struct audio_port_config config; |
| data.read(&config, sizeof(struct audio_port_config)); |
| status_t status = setAudioPortConfig(&config); |
| reply->writeInt32(status); |
| return NO_ERROR; |
| } |
| |
| case REGISTER_CLIENT: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>( |
| data.readStrongBinder()); |
| registerClient(client); |
| return NO_ERROR; |
| } break; |
| |
| case SET_AUDIO_PORT_CALLBACK_ENABLED: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| setAudioPortCallbacksEnabled(data.readInt32() == 1); |
| return NO_ERROR; |
| } break; |
| |
| case ACQUIRE_SOUNDTRIGGER_SESSION: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>( |
| data.readStrongBinder()); |
| audio_session_t session = AUDIO_SESSION_NONE; |
| audio_io_handle_t ioHandle = AUDIO_IO_HANDLE_NONE; |
| audio_devices_t device = AUDIO_DEVICE_NONE; |
| status_t status = acquireSoundTriggerSession(&session, &ioHandle, &device); |
| reply->writeInt32(status); |
| if (status == NO_ERROR) { |
| reply->writeInt32(session); |
| reply->writeInt32(ioHandle); |
| reply->writeInt32(device); |
| } |
| return NO_ERROR; |
| } break; |
| |
| case RELEASE_SOUNDTRIGGER_SESSION: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>( |
| data.readStrongBinder()); |
| audio_session_t session = (audio_session_t)data.readInt32(); |
| status_t status = releaseSoundTriggerSession(session); |
| reply->writeInt32(status); |
| return NO_ERROR; |
| } break; |
| |
| case GET_PHONE_STATE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| reply->writeInt32((int32_t)getPhoneState()); |
| return NO_ERROR; |
| } break; |
| |
| case REGISTER_POLICY_MIXES: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| bool registration = data.readInt32() == 1; |
| Vector<AudioMix> mixes; |
| size_t size = (size_t)data.readInt32(); |
| if (size > MAX_MIXES_PER_POLICY) { |
| size = MAX_MIXES_PER_POLICY; |
| } |
| for (size_t i = 0; i < size; i++) { |
| AudioMix mix; |
| if (mix.readFromParcel((Parcel*)&data) == NO_ERROR) { |
| mixes.add(mix); |
| } |
| } |
| status_t status = registerPolicyMixes(mixes, registration); |
| reply->writeInt32(status); |
| return NO_ERROR; |
| } break; |
| |
| case START_AUDIO_SOURCE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| struct audio_port_config source; |
| data.read(&source, sizeof(struct audio_port_config)); |
| audio_attributes_t attributes; |
| data.read(&attributes, sizeof(audio_attributes_t)); |
| sanetizeAudioAttributes(&attributes); |
| audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE; |
| status_t status = startAudioSource(&source, &attributes, &handle); |
| reply->writeInt32(status); |
| reply->writeInt32(handle); |
| return NO_ERROR; |
| } break; |
| |
| case STOP_AUDIO_SOURCE: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_patch_handle_t handle = (audio_patch_handle_t) data.readInt32(); |
| status_t status = stopAudioSource(handle); |
| reply->writeInt32(status); |
| return NO_ERROR; |
| } break; |
| |
| case SET_MASTER_MONO: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| bool mono = static_cast<bool>(data.readInt32()); |
| status_t status = setMasterMono(mono); |
| reply->writeInt32(status); |
| return NO_ERROR; |
| } break; |
| |
| case GET_MASTER_MONO: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| bool mono; |
| status_t status = getMasterMono(&mono); |
| reply->writeInt32(status); |
| if (status == NO_ERROR) { |
| reply->writeInt32(static_cast<int32_t>(mono)); |
| } |
| return NO_ERROR; |
| } break; |
| |
| case GET_STREAM_VOLUME_DB: { |
| CHECK_INTERFACE(IAudioPolicyService, data, reply); |
| audio_stream_type_t stream = |
| static_cast <audio_stream_type_t>(data.readInt32()); |
| int index = static_cast <int>(data.readInt32()); |
| audio_devices_t device = |
| static_cast <audio_devices_t>(data.readUint32()); |
| reply->writeFloat(getStreamVolumeDB(stream, index, device)); |
| return NO_ERROR; |
| } |
| |
| default: |
| return BBinder::onTransact(code, data, reply, flags); |
| } |
| } |
| |
| void BnAudioPolicyService::sanetizeAudioAttributes(audio_attributes_t* attr) |
| { |
| const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE; |
| if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) { |
| android_errorWriteLog(0x534e4554, "68953950"); // SafetyNet logging |
| } |
| attr->tags[tagsMaxSize - 1] = '\0'; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| } // namespace android |