/* ** ** 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 #include #include #include #include #include #include #include #include #include #include #include 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, GET_SURROUND_FORMATS, SET_SURROUND_FORMAT_ENABLED }; #define MAX_ITEMS_PER_LIST 1024 class BpAudioPolicyService : public BpInterface { public: explicit BpAudioPolicyService(const sp& impl) : BpInterface(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 (device)); data.writeInt32(static_cast (state)); data.writeCString(device_address); data.writeCString(device_name); remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply); return static_cast (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 (device)); data.writeCString(device_address); remote()->transact(GET_DEVICE_CONNECTION_STATE, data, &reply); return static_cast (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 (device)); data.writeCString(device_address); data.writeCString(device_name); remote()->transact(HANDLE_DEVICE_CONFIG_CHANGE, data, &reply); return static_cast (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 (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 (usage)); data.writeInt32(static_cast (config)); remote()->transact(SET_FORCE_USE, data, &reply); return static_cast (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 (usage)); remote()->transact(GET_FORCE_USE, data, &reply); return static_cast (reply.readInt32()); } virtual audio_io_handle_t getOutput(audio_stream_type_t stream) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(static_cast (stream)); remote()->transact(GET_OUTPUT, data, &reply); return static_cast (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, pid_t pid, 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(pid); data.writeInt32(uid); data.write(config, sizeof(audio_config_t)); data.writeInt32(static_cast (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 (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 (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 String16& opPackageName, 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.writeString16(opPackageName); 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_port_handle_t portId, bool *silenced) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(portId); data.writeInt32(*silenced ? 1 : 0); remote()->transact(START_INPUT, data, &reply); status_t status = static_cast (reply.readInt32()); *silenced = reply.readInt32() == 1; return status; } virtual status_t stopInput(audio_port_handle_t portId) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(portId); remote()->transact(STOP_INPUT, data, &reply); return static_cast (reply.readInt32()); } virtual void releaseInput(audio_port_handle_t portId) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(portId); 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 (stream)); data.writeInt32(indexMin); data.writeInt32(indexMax); remote()->transact(INIT_STREAM_VOLUME, data, &reply); return static_cast (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 (stream)); data.writeInt32(index); data.writeInt32(static_cast (device)); remote()->transact(SET_STREAM_VOLUME, data, &reply); return static_cast (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 (stream)); data.writeInt32(static_cast (device)); remote()->transact(GET_STREAM_VOLUME, data, &reply); int lIndex = reply.readInt32(); if (index) *index = lIndex; return static_cast (reply.readInt32()); } virtual uint32_t getStrategyForStream(audio_stream_type_t stream) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(static_cast (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 (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 (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 (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 (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 (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 (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& 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& 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(mono)); status_t status = remote()->transact(SET_MASTER_MONO, data, &reply); if (status != NO_ERROR) { return status; } return static_cast(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(reply.readInt32()); if (status == NO_ERROR) { *mono = static_cast(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 (stream)); data.writeInt32(static_cast (index)); data.writeUint32(static_cast (device)); status_t status = remote()->transact(GET_STREAM_VOLUME_DB, data, &reply); if (status != NO_ERROR) { return NAN; } return reply.readFloat(); } virtual status_t getSurroundFormats(unsigned int *numSurroundFormats, audio_format_t *surroundFormats, bool *surroundFormatsEnabled, bool reported) { if (numSurroundFormats == NULL || (*numSurroundFormats != 0 && (surroundFormats == NULL || surroundFormatsEnabled == NULL))) { return BAD_VALUE; } Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); unsigned int numSurroundFormatsReq = *numSurroundFormats; data.writeUint32(numSurroundFormatsReq); data.writeBool(reported); status_t status = remote()->transact(GET_SURROUND_FORMATS, data, &reply); if (status == NO_ERROR && (status = (status_t)reply.readInt32()) == NO_ERROR) { *numSurroundFormats = reply.readUint32(); } if (status == NO_ERROR) { if (numSurroundFormatsReq > *numSurroundFormats) { numSurroundFormatsReq = *numSurroundFormats; } if (numSurroundFormatsReq > 0) { status = reply.read(surroundFormats, numSurroundFormatsReq * sizeof(audio_format_t)); if (status != NO_ERROR) { return status; } status = reply.read(surroundFormatsEnabled, numSurroundFormatsReq * sizeof(bool)); } } return status; } virtual status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(audioFormat); data.writeBool(enabled); status_t status = remote()->transact(SET_SURROUND_FORMAT_ENABLED, data, &reply); if (status != NO_ERROR) { return status; } return reply.readInt32(); } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); // ---------------------------------------------------------------------- status_t BnAudioPolicyService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // make sure transactions reserved to AudioFlinger do not come from other processes switch (code) { case START_OUTPUT: case STOP_OUTPUT: case RELEASE_OUTPUT: case GET_INPUT_FOR_ATTR: case START_INPUT: case STOP_INPUT: case RELEASE_INPUT: case GET_STRATEGY_FOR_STREAM: case GET_OUTPUT_FOR_EFFECT: case REGISTER_EFFECT: case UNREGISTER_EFFECT: case SET_EFFECT_ENABLED: case GET_OUTPUT_FOR_ATTR: case ACQUIRE_SOUNDTRIGGER_SESSION: case RELEASE_SOUNDTRIGGER_SESSION: ALOGW("%s: transaction %d received from PID %d", __func__, code, IPCThreadState::self()->getCallingPid()); // return status only for non void methods switch (code) { case RELEASE_OUTPUT: case RELEASE_INPUT: break; default: reply->writeInt32(static_cast (INVALID_OPERATION)); break; } return OK; default: break; } // make sure the following transactions come from system components switch (code) { case SET_DEVICE_CONNECTION_STATE: case HANDLE_DEVICE_CONFIG_CHANGE: case SET_PHONE_STATE: //FIXME: Allow SET_FORCE_USE calls from system apps until a better use case routing API is available // case SET_FORCE_USE: case INIT_STREAM_VOLUME: case SET_STREAM_VOLUME: case REGISTER_POLICY_MIXES: case SET_MASTER_MONO: case START_AUDIO_SOURCE: case STOP_AUDIO_SOURCE: case GET_SURROUND_FORMATS: case SET_SURROUND_FORMAT_ENABLED: { if (multiuser_get_app_id(IPCThreadState::self()->getCallingUid()) >= AID_APP_START) { ALOGW("%s: transaction %d received from PID %d unauthorized UID %d", __func__, code, IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); reply->writeInt32(static_cast (INVALID_OPERATION)); return OK; } } break; default: break; } TimeCheck check("IAudioPolicyService"); switch (code) { case SET_DEVICE_CONNECTION_STATE: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_devices_t device = static_cast (data.readInt32()); audio_policy_dev_state_t state = static_cast (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 (BAD_VALUE)); } else { reply->writeInt32(static_cast (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 (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 (AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)); } else { reply->writeInt32(static_cast (getDeviceConnectionState(device, device_address))); } return NO_ERROR; } break; case HANDLE_DEVICE_CONFIG_CHANGE: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_devices_t device = static_cast (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 (BAD_VALUE)); } else { reply->writeInt32(static_cast (handleDeviceConfigChange(device, device_address, device_name))); } return NO_ERROR; } break; case SET_PHONE_STATE: { CHECK_INTERFACE(IAudioPolicyService, data, reply); reply->writeInt32(static_cast (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 ( data.readInt32()); audio_policy_forced_cfg_t config = static_cast (data.readInt32()); reply->writeInt32(static_cast (setForceUse(usage, config))); return NO_ERROR; } break; case GET_FORCE_USE: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_policy_force_use_t usage = static_cast ( data.readInt32()); reply->writeInt32(static_cast (getForceUse(usage))); return NO_ERROR; } break; case GET_OUTPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = static_cast (data.readInt32()); audio_io_handle_t output = getOutput(stream); reply->writeInt32(static_cast (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(); } pid_t pid = (pid_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 (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, pid, 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 (data.readInt32()); audio_stream_type_t stream = static_cast (data.readInt32()); audio_session_t session = (audio_session_t)data.readInt32(); reply->writeInt32(static_cast (startOutput(output, stream, session))); return NO_ERROR; } break; case STOP_OUTPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t output = static_cast (data.readInt32()); audio_stream_type_t stream = static_cast (data.readInt32()); audio_session_t session = (audio_session_t)data.readInt32(); reply->writeInt32(static_cast (stopOutput(output, stream, session))); return NO_ERROR; } break; case RELEASE_OUTPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t output = static_cast (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(); const String16 opPackageName = data.readString16(); 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, opPackageName, &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_port_handle_t portId = static_cast (data.readInt32()); bool silenced = data.readInt32() == 1; status_t status = startInput(portId, &silenced); reply->writeInt32(static_cast (status)); reply->writeInt32(silenced ? 1 : 0); return NO_ERROR; } break; case STOP_INPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_port_handle_t portId = static_cast (data.readInt32()); reply->writeInt32(static_cast (stopInput(portId))); return NO_ERROR; } break; case RELEASE_INPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_port_handle_t portId = static_cast (data.readInt32()); releaseInput(portId); return NO_ERROR; } break; case INIT_STREAM_VOLUME: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = static_cast (data.readInt32()); int indexMin = data.readInt32(); int indexMax = data.readInt32(); reply->writeInt32(static_cast (initStreamVolume(stream, indexMin,indexMax))); return NO_ERROR; } break; case SET_STREAM_VOLUME: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = static_cast (data.readInt32()); int index = data.readInt32(); audio_devices_t device = static_cast (data.readInt32()); reply->writeInt32(static_cast (setStreamVolumeIndex(stream, index, device))); return NO_ERROR; } break; case GET_STREAM_VOLUME: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = static_cast (data.readInt32()); audio_devices_t device = static_cast (data.readInt32()); int index = 0; status_t status = getStreamVolumeIndex(stream, &index, device); reply->writeInt32(index); reply->writeInt32(static_cast (status)); return NO_ERROR; } break; case GET_STRATEGY_FOR_STREAM: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = static_cast (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 (data.readInt32()); reply->writeInt32(static_cast (getDevicesForStream(stream))); return NO_ERROR; } break; case GET_OUTPUT_FOR_EFFECT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); effect_descriptor_t desc = {}; if (data.read(&desc, sizeof(desc)) != NO_ERROR) { android_errorWriteLog(0x534e4554, "73126106"); } (void)sanitizeEffectDescriptor(&desc); audio_io_handle_t output = getOutputForEffect(&desc); reply->writeInt32(static_cast (output)); return NO_ERROR; } break; case REGISTER_EFFECT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); effect_descriptor_t desc = {}; if (data.read(&desc, sizeof(desc)) != NO_ERROR) { android_errorWriteLog(0x534e4554, "73126106"); } (void)sanitizeEffectDescriptor(&desc); 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 (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 (unregisterEffect(id))); return NO_ERROR; } break; case SET_EFFECT_ENABLED: { CHECK_INTERFACE(IAudioPolicyService, data, reply); int id = data.readInt32(); bool enabled = static_cast (data.readInt32()); reply->writeInt32(static_cast (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 = AUDIO_PATCH_HANDLE_NONE; 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)); (void)sanitizeAudioPortConfig(&config); status_t status = setAudioPortConfig(&config); reply->writeInt32(status); return NO_ERROR; } case REGISTER_CLIENT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); sp client = interface_cast( 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 client = interface_cast( 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 client = interface_cast( 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 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)); (void)sanitizeAudioPortConfig(&source); 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(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(mono)); } return NO_ERROR; } break; case GET_STREAM_VOLUME_DB: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = static_cast (data.readInt32()); int index = static_cast (data.readInt32()); audio_devices_t device = static_cast (data.readUint32()); reply->writeFloat(getStreamVolumeDB(stream, index, device)); return NO_ERROR; } case GET_SURROUND_FORMATS: { CHECK_INTERFACE(IAudioPolicyService, data, reply); unsigned int numSurroundFormatsReq = data.readUint32(); if (numSurroundFormatsReq > MAX_ITEMS_PER_LIST) { numSurroundFormatsReq = MAX_ITEMS_PER_LIST; } bool reported = data.readBool(); unsigned int numSurroundFormats = numSurroundFormatsReq; audio_format_t *surroundFormats = (audio_format_t *)calloc( numSurroundFormats, sizeof(audio_format_t)); bool *surroundFormatsEnabled = (bool *)calloc(numSurroundFormats, sizeof(bool)); if (numSurroundFormatsReq > 0 && (surroundFormats == NULL || surroundFormatsEnabled == NULL)) { free(surroundFormats); free(surroundFormatsEnabled); reply->writeInt32(NO_MEMORY); return NO_ERROR; } status_t status = getSurroundFormats( &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported); reply->writeInt32(status); if (status == NO_ERROR) { reply->writeUint32(numSurroundFormats); if (numSurroundFormatsReq > numSurroundFormats) { numSurroundFormatsReq = numSurroundFormats; } reply->write(surroundFormats, numSurroundFormatsReq * sizeof(audio_format_t)); reply->write(surroundFormatsEnabled, numSurroundFormatsReq * sizeof(bool)); } free(surroundFormats); free(surroundFormatsEnabled); return NO_ERROR; } case SET_SURROUND_FORMAT_ENABLED: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_format_t audioFormat = (audio_format_t) data.readInt32(); bool enabled = data.readBool(); status_t status = setSurroundFormatEnabled(audioFormat, enabled); reply->writeInt32(status); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } } /** returns true if string overflow was prevented by zero termination */ template static bool preventStringOverflow(char (&s)[size]) { if (strnlen(s, size) < size) return false; s[size - 1] = '\0'; return true; } 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'; } /** returns BAD_VALUE if sanitization was required. */ status_t BnAudioPolicyService::sanitizeEffectDescriptor(effect_descriptor_t* desc) { if (preventStringOverflow(desc->name) | /* always */ preventStringOverflow(desc->implementor)) { android_errorWriteLog(0x534e4554, "73126106"); // SafetyNet logging return BAD_VALUE; } return NO_ERROR; } /** returns BAD_VALUE if sanitization was required. */ status_t BnAudioPolicyService::sanitizeAudioPortConfig(struct audio_port_config* config) { if (config->type == AUDIO_PORT_TYPE_DEVICE && preventStringOverflow(config->ext.device.address)) { return BAD_VALUE; } return NO_ERROR; } // ---------------------------------------------------------------------------- } // namespace android