Merge "External camera: add device config file"
diff --git a/audio/4.0/Android.bp b/audio/4.0/Android.bp
new file mode 100644
index 0000000..6e217d9
--- /dev/null
+++ b/audio/4.0/Android.bp
@@ -0,0 +1,48 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.audio@4.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IDevice.hal",
+ "IDevicesFactory.hal",
+ "IPrimaryDevice.hal",
+ "IStream.hal",
+ "IStreamIn.hal",
+ "IStreamOut.hal",
+ "IStreamOutCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio.common@4.0",
+ "android.hardware.audio.effect@4.0",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "AudioDrain",
+ "AudioFrequencyResponsePoint",
+ "AudioMicrophoneChannelMapping",
+ "AudioMicrophoneCoordinate",
+ "AudioMicrophoneDirectionality",
+ "AudioMicrophoneLocation",
+ "DeviceAddress",
+ "MessageQueueFlagBits",
+ "MicrophoneInfo",
+ "MmapBufferFlag",
+ "MmapBufferInfo",
+ "MmapPosition",
+ "ParameterValue",
+ "PlaybackTrackMetadata",
+ "RecordTrackMetadata",
+ "Result",
+ "SinkMetadata",
+ "SourceMetadata",
+ "TimeSpec",
+ ],
+ gen_java: false,
+ gen_java_constants: true,
+}
+
diff --git a/audio/4.0/IDevice.hal b/audio/4.0/IDevice.hal
new file mode 100644
index 0000000..bb58568
--- /dev/null
+++ b/audio/4.0/IDevice.hal
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IStreamIn;
+import IStreamOut;
+
+interface IDevice {
+ /**
+ * Returns whether the audio hardware interface has been initialized.
+ *
+ * @return retval OK on success, NOT_INITIALIZED on failure.
+ */
+ initCheck() generates (Result retval);
+
+ /**
+ * Sets the audio volume for all audio activities other than voice call. If
+ * NOT_SUPPORTED is returned, the software mixer will emulate this
+ * capability.
+ *
+ * @param volume 1.0f means unity, 0.0f is zero.
+ * @return retval operation completion status.
+ */
+ setMasterVolume(float volume) generates (Result retval);
+
+ /**
+ * Get the current master volume value for the HAL, if the HAL supports
+ * master volume control. For example, AudioFlinger will query this value
+ * from the primary audio HAL when the service starts and use the value for
+ * setting the initial master volume across all HALs. HALs which do not
+ * support this method must return NOT_SUPPORTED in 'retval'.
+ *
+ * @return retval operation completion status.
+ * @return volume 1.0f means unity, 0.0f is zero.
+ */
+ getMasterVolume() generates (Result retval, float volume);
+
+ /**
+ * Sets microphone muting state.
+ *
+ * @param mute whether microphone is muted.
+ * @return retval operation completion status.
+ */
+ setMicMute(bool mute) generates (Result retval);
+
+ /**
+ * Gets whether microphone is muted.
+ *
+ * @return retval operation completion status.
+ * @return mute whether microphone is muted.
+ */
+ getMicMute() generates (Result retval, bool mute);
+
+ /**
+ * Set the audio mute status for all audio activities. If the return value
+ * is NOT_SUPPORTED, the software mixer will emulate this capability.
+ *
+ * @param mute whether audio is muted.
+ * @return retval operation completion status.
+ */
+ setMasterMute(bool mute) generates (Result retval);
+
+ /**
+ * Get the current master mute status for the HAL, if the HAL supports
+ * master mute control. AudioFlinger will query this value from the primary
+ * audio HAL when the service starts and use the value for setting the
+ * initial master mute across all HALs. HAL must indicate that the feature
+ * is not supported by returning NOT_SUPPORTED status.
+ *
+ * @return retval operation completion status.
+ * @return mute whether audio is muted.
+ */
+ getMasterMute() generates (Result retval, bool mute);
+
+ /**
+ * Returns audio input buffer size according to parameters passed or
+ * INVALID_ARGUMENTS if one of the parameters is not supported.
+ *
+ * @param config audio configuration.
+ * @return retval operation completion status.
+ * @return bufferSize input buffer size in bytes.
+ */
+ getInputBufferSize(AudioConfig config)
+ generates (Result retval, uint64_t bufferSize);
+
+ /**
+ * This method creates and opens the audio hardware output stream.
+ * If the stream can not be opened with the proposed audio config,
+ * HAL must provide suggested values for the audio config.
+ *
+ * @param ioHandle handle assigned by AudioFlinger.
+ * @param device device type and (if needed) address.
+ * @param config stream configuration.
+ * @param flags additional flags.
+ * @param sourceMetadata Description of the audio that will be played.
+ May be used by implementations to configure hardware effects.
+ * @return retval operation completion status.
+ * @return outStream created output stream.
+ * @return suggestedConfig in case of invalid parameters, suggested config.
+ */
+ openOutputStream(
+ AudioIoHandle ioHandle,
+ DeviceAddress device,
+ AudioConfig config,
+ bitfield<AudioOutputFlag> flags,
+ SourceMetadata sourceMetadata) generates (
+ Result retval,
+ IStreamOut outStream,
+ AudioConfig suggestedConfig);
+
+ /**
+ * This method creates and opens the audio hardware input stream.
+ * If the stream can not be opened with the proposed audio config,
+ * HAL must provide suggested values for the audio config.
+ *
+ * @param ioHandle handle assigned by AudioFlinger.
+ * @param device device type and (if needed) address.
+ * @param config stream configuration.
+ * @param flags additional flags.
+ * @param source source specification.
+ * @param sinkMetadata Description of the audio that is suggested by the client.
+ * May be used by implementations to configure hardware effects.
+ * @return retval operation completion status.
+ * @return inStream in case of success, created input stream.
+ * @return suggestedConfig in case of invalid parameters, suggested config.
+ */
+ openInputStream(
+ AudioIoHandle ioHandle,
+ DeviceAddress device,
+ AudioConfig config,
+ bitfield<AudioInputFlag> flags,
+ SinkMetadata sinkMetadata) generates (
+ Result retval,
+ IStreamIn inStream,
+ AudioConfig suggestedConfig);
+
+ /**
+ * Returns whether HAL supports audio patches.
+ *
+ * @return supports true if audio patches are supported.
+ */
+ supportsAudioPatches() generates (bool supports);
+
+ /**
+ * Creates an audio patch between several source and sink ports. The handle
+ * is allocated by the HAL and must be unique for this audio HAL module.
+ *
+ * @param sources patch sources.
+ * @param sinks patch sinks.
+ * @return retval operation completion status.
+ * @return patch created patch handle.
+ */
+ createAudioPatch(vec<AudioPortConfig> sources, vec<AudioPortConfig> sinks)
+ generates (Result retval, AudioPatchHandle patch);
+
+ /**
+ * Release an audio patch.
+ *
+ * @param patch patch handle.
+ * @return retval operation completion status.
+ */
+ releaseAudioPatch(AudioPatchHandle patch) generates (Result retval);
+
+ /**
+ * Returns the list of supported attributes for a given audio port.
+ *
+ * As input, 'port' contains the information (type, role, address etc...)
+ * needed by the HAL to identify the port.
+ *
+ * As output, 'resultPort' contains possible attributes (sampling rates,
+ * formats, channel masks, gain controllers...) for this port.
+ *
+ * @param port port identifier.
+ * @return retval operation completion status.
+ * @return resultPort port descriptor with all parameters filled up.
+ */
+ getAudioPort(AudioPort port)
+ generates (Result retval, AudioPort resultPort);
+
+ /**
+ * Set audio port configuration.
+ *
+ * @param config audio port configuration.
+ * @return retval operation completion status.
+ */
+ setAudioPortConfig(AudioPortConfig config) generates (Result retval);
+
+ /**
+ * Gets the HW synchronization source of the device. Calling this method is
+ * equivalent to getting AUDIO_PARAMETER_HW_AV_SYNC on the legacy HAL.
+ * Optional method
+ *
+ * @return retval operation completion status: OK or NOT_SUPPORTED.
+ * @return hwAvSync HW synchronization source
+ */
+ getHwAvSync() generates (Result retval, AudioHwSync hwAvSync);
+
+ /**
+ * Sets whether the screen is on. Calling this method is equivalent to
+ * setting AUDIO_PARAMETER_KEY_SCREEN_STATE on the legacy HAL.
+ * Optional method
+ *
+ * @param turnedOn whether the screen is turned on.
+ * @return retval operation completion status.
+ */
+ setScreenState(bool turnedOn) generates (Result retval);
+
+ /**
+ * Generic method for retrieving vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * Multiple parameters can be retrieved at the same time.
+ * The implementation should return as many requested parameters
+ * as possible, even if one or more is not supported
+ *
+ * @param context provides more information about the request
+ * @param keys keys of the requested parameters
+ * @return retval operation completion status.
+ * OK must be returned if keys is empty.
+ * NOT_SUPPORTED must be returned if at least one key is unknown.
+ * @return parameters parameter key value pairs.
+ * Must contain the value of all requested keys if retval == OK
+ */
+ getParameters(vec<ParameterValue> context, vec<string> keys)
+ generates (Result retval, vec<ParameterValue> parameters);
+
+ /**
+ * Generic method for setting vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * Multiple parameters can be set at the same time though this is
+ * discouraged as it make failure analysis harder.
+ *
+ * If possible, a failed setParameters should not impact the platform state.
+ *
+ * @param context provides more information about the request
+ * @param parameters parameter key value pairs.
+ * @return retval operation completion status.
+ * All parameters must be successfully set for OK to be returned
+ */
+ setParameters(vec<ParameterValue> context, vec<ParameterValue> parameters)
+ generates (Result retval);
+
+ /**
+ * Returns an array with available microphones in device.
+ *
+ * @return retval INVALID_STATE if the call is not successful,
+ * OK otherwise.
+ *
+ * @return microphones array with microphones info
+ */
+ getMicrophones()
+ generates(Result retval, vec<MicrophoneInfo> microphones);
+};
diff --git a/audio/4.0/IDevicesFactory.hal b/audio/4.0/IDevicesFactory.hal
new file mode 100644
index 0000000..c552c6d
--- /dev/null
+++ b/audio/4.0/IDevicesFactory.hal
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IDevice;
+
+interface IDevicesFactory {
+ /** Allows a HAL implementation to be split in multiple independent
+ * devices (called module in the pre-treble API).
+ * Note that this division is arbitrary and implementation are free
+ * to only have a Primary.
+ * The framework will query the devices according to audio_policy_configuration.xml
+ *
+ * Each Device value is interchangeable with any other and the framework
+ * does not differentiate between values with the following exceptions:
+ * - the Primary device must always be present
+ * - the R_SUBMIX that is used to forward audio of REMOTE_SUBMIX DEVICES
+ */
+ enum Device : int32_t {
+ PRIMARY,
+ A2DP,
+ USB,
+ R_SUBMIX,
+ STUB,
+ CODEC_OFFLOAD,
+ SECONDARY,
+ AUXILIARY,
+ /** Multi Stream Decoder */
+ MSD
+ };
+
+ /**
+ * Opens an audio device. To close the device, it is necessary to release
+ * references to the returned device object.
+ *
+ * @param device device type.
+ * @return retval operation completion status. Returns INVALID_ARGUMENTS
+ * if there is no corresponding hardware module found,
+ * NOT_INITIALIZED if an error occured while opening the hardware
+ * module.
+ * @return result the interface for the created device.
+ */
+ openDevice(Device device) generates (Result retval, IDevice result);
+};
diff --git a/audio/4.0/IPrimaryDevice.hal b/audio/4.0/IPrimaryDevice.hal
new file mode 100644
index 0000000..f3d904c
--- /dev/null
+++ b/audio/4.0/IPrimaryDevice.hal
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IDevice;
+
+interface IPrimaryDevice extends IDevice {
+ /**
+ * Sets the audio volume of a voice call.
+ *
+ * @param volume 1.0f means unity, 0.0f is zero.
+ * @return retval operation completion status.
+ */
+ setVoiceVolume(float volume) generates (Result retval);
+
+ /**
+ * This method is used to notify the HAL about audio mode changes.
+ *
+ * @param mode new mode.
+ * @return retval operation completion status.
+ */
+ setMode(AudioMode mode) generates (Result retval);
+
+ /**
+ * Gets whether BT SCO Noise Reduction and Echo Cancellation are enabled.
+ * Calling this method is equivalent to getting AUDIO_PARAMETER_KEY_BT_NREC
+ * on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return enabled whether BT SCO NR + EC are enabled.
+ */
+ getBtScoNrecEnabled() generates (Result retval, bool enabled);
+
+ /**
+ * Sets whether BT SCO Noise Reduction and Echo Cancellation are enabled.
+ * Calling this method is equivalent to setting AUDIO_PARAMETER_KEY_BT_NREC
+ * on the legacy HAL.
+ * Optional method
+ *
+ * @param enabled whether BT SCO NR + EC are enabled.
+ * @return retval operation completion status.
+ */
+ setBtScoNrecEnabled(bool enabled) generates (Result retval);
+
+ /**
+ * Gets whether BT SCO Wideband mode is enabled. Calling this method is
+ * equivalent to getting AUDIO_PARAMETER_KEY_BT_SCO_WB on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return enabled whether BT Wideband is enabled.
+ */
+ getBtScoWidebandEnabled() generates (Result retval, bool enabled);
+
+ /**
+ * Sets whether BT SCO Wideband mode is enabled. Calling this method is
+ * equivalent to setting AUDIO_PARAMETER_KEY_BT_SCO_WB on the legacy HAL.
+ * Optional method
+ *
+ * @param enabled whether BT Wideband is enabled.
+ * @return retval operation completion status.
+ */
+ setBtScoWidebandEnabled(bool enabled) generates (Result retval);
+
+ enum TtyMode : int32_t {
+ OFF,
+ VCO,
+ HCO,
+ FULL
+ };
+
+ /**
+ * Gets current TTY mode selection. Calling this method is equivalent to
+ * getting AUDIO_PARAMETER_KEY_TTY_MODE on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return mode TTY mode.
+ */
+ getTtyMode() generates (Result retval, TtyMode mode);
+
+ /**
+ * Sets current TTY mode. Calling this method is equivalent to setting
+ * AUDIO_PARAMETER_KEY_TTY_MODE on the legacy HAL.
+ *
+ * @param mode TTY mode.
+ * @return retval operation completion status.
+ */
+ setTtyMode(TtyMode mode) generates (Result retval);
+
+ /**
+ * Gets whether Hearing Aid Compatibility - Telecoil (HAC-T) mode is
+ * enabled. Calling this method is equivalent to getting
+ * AUDIO_PARAMETER_KEY_HAC on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return enabled whether HAC mode is enabled.
+ */
+ getHacEnabled() generates (Result retval, bool enabled);
+
+ /**
+ * Sets whether Hearing Aid Compatibility - Telecoil (HAC-T) mode is
+ * enabled. Calling this method is equivalent to setting
+ * AUDIO_PARAMETER_KEY_HAC on the legacy HAL.
+ * Optional method
+ *
+ * @param enabled whether HAC mode is enabled.
+ * @return retval operation completion status.
+ */
+ setHacEnabled(bool enabled) generates (Result retval);
+};
diff --git a/audio/4.0/IStream.hal b/audio/4.0/IStream.hal
new file mode 100644
index 0000000..f05d7b0
--- /dev/null
+++ b/audio/4.0/IStream.hal
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import android.hardware.audio.effect@4.0::IEffect;
+
+interface IStream {
+ /**
+ * Return the frame size (number of bytes per sample).
+ *
+ * @return frameSize frame size in bytes.
+ */
+ getFrameSize() generates (uint64_t frameSize);
+
+ /**
+ * Return the frame count of the buffer. Calling this method is equivalent
+ * to getting AUDIO_PARAMETER_STREAM_FRAME_COUNT on the legacy HAL.
+ *
+ * @return count frame count.
+ */
+ getFrameCount() generates (uint64_t count);
+
+ /**
+ * Return the size of input/output buffer in bytes for this stream.
+ * It must be a multiple of the frame size.
+ *
+ * @return buffer buffer size in bytes.
+ */
+ getBufferSize() generates (uint64_t bufferSize);
+
+ /**
+ * Return the sampling rate in Hz.
+ *
+ * @return sampleRateHz sample rate in Hz.
+ */
+ getSampleRate() generates (uint32_t sampleRateHz);
+
+ /**
+ * Return supported native sampling rates of the stream for a given format.
+ * A supported native sample rate is a sample rate that can be efficiently
+ * played by the hardware (typically without sample-rate conversions).
+ *
+ * This function is only called for dynamic profile. If called for
+ * non-dynamic profile is should return NOT_SUPPORTED or the same list
+ * as in audio_policy_configuration.xml.
+ *
+ * Calling this method is equivalent to getting
+ * AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES on the legacy HAL.
+ *
+ *
+ * @param format audio format for which the sample rates are supported.
+ * @return retval operation completion status.
+ * Must be OK if the format is supported.
+ * @return sampleRateHz supported sample rates.
+ */
+ getSupportedSampleRates(AudioFormat format)
+ generates (Result retval, vec<uint32_t> sampleRates);
+
+ /**
+ * Sets the sampling rate of the stream. Calling this method is equivalent
+ * to setting AUDIO_PARAMETER_STREAM_SAMPLING_RATE on the legacy HAL.
+ * Optional method. If implemented, only called on a stopped stream.
+ *
+ * @param sampleRateHz sample rate in Hz.
+ * @return retval operation completion status.
+ */
+ setSampleRate(uint32_t sampleRateHz) generates (Result retval);
+
+ /**
+ * Return the channel mask of the stream.
+ *
+ * @return mask channel mask.
+ */
+ getChannelMask() generates (bitfield<AudioChannelMask> mask);
+
+ /**
+ * Return supported channel masks of the stream. Calling this method is
+ * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_CHANNELS on the legacy
+ * HAL.
+ *
+ * @param format audio format for which the channel masks are supported.
+ * @return retval operation completion status.
+ * Must be OK if the format is supported.
+ * @return masks supported audio masks.
+ */
+ getSupportedChannelMasks(AudioFormat format)
+ generates (Result retval, vec<bitfield<AudioChannelMask>> masks);
+
+ /**
+ * Sets the channel mask of the stream. Calling this method is equivalent to
+ * setting AUDIO_PARAMETER_STREAM_CHANNELS on the legacy HAL.
+ * Optional method
+ *
+ * @param format audio format.
+ * @return retval operation completion status.
+ */
+ setChannelMask(bitfield<AudioChannelMask> mask) generates (Result retval);
+
+ /**
+ * Return the audio format of the stream.
+ *
+ * @return format audio format.
+ */
+ getFormat() generates (AudioFormat format);
+
+ /**
+ * Return supported audio formats of the stream. Calling this method is
+ * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_FORMATS on the legacy
+ * HAL.
+ *
+ * @return formats supported audio formats.
+ */
+ getSupportedFormats() generates (vec<AudioFormat> formats);
+
+ /**
+ * Sets the audio format of the stream. Calling this method is equivalent to
+ * setting AUDIO_PARAMETER_STREAM_FORMAT on the legacy HAL.
+ * Optional method
+ *
+ * @param format audio format.
+ * @return retval operation completion status.
+ */
+ setFormat(AudioFormat format) generates (Result retval);
+
+ /**
+ * Convenience method for retrieving several stream parameters in
+ * one transaction.
+ *
+ * @return sampleRateHz sample rate in Hz.
+ * @return mask channel mask.
+ * @return format audio format.
+ */
+ getAudioProperties() generates (
+ uint32_t sampleRateHz, bitfield<AudioChannelMask> mask, AudioFormat format);
+
+ /**
+ * Applies audio effect to the stream.
+ *
+ * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+ * the effect to apply.
+ * @return retval operation completion status.
+ */
+ addEffect(uint64_t effectId) generates (Result retval);
+
+ /**
+ * Stops application of the effect to the stream.
+ *
+ * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+ * the effect to remove.
+ * @return retval operation completion status.
+ */
+ removeEffect(uint64_t effectId) generates (Result retval);
+
+ /**
+ * Put the audio hardware input/output into standby mode.
+ * Driver must exit from standby mode at the next I/O operation.
+ *
+ * @return retval operation completion status.
+ */
+ standby() generates (Result retval);
+
+ /**
+ * Return the set of device(s) which this stream is connected to.
+ * Optional method
+ *
+ * @return retval operation completion status: OK or NOT_SUPPORTED.
+ * @return device set of device(s) which this stream is connected to.
+ */
+ getDevice() generates (Result retval, bitfield<AudioDevice> device);
+
+ /**
+ * Connects the stream to the device.
+ *
+ * This method must only be used for HALs that do not support
+ * 'IDevice.createAudioPatch' method. Calling this method is
+ * equivalent to setting AUDIO_PARAMETER_STREAM_ROUTING in the legacy HAL
+ * interface.
+ *
+ * @param address device to connect the stream to.
+ * @return retval operation completion status.
+ */
+ setDevice(DeviceAddress address) generates (Result retval);
+
+ /**
+ * Notifies the stream about device connection state. Calling this method is
+ * equivalent to setting AUDIO_PARAMETER_DEVICE_[DIS]CONNECT on the legacy
+ * HAL.
+ *
+ * @param address audio device specification.
+ * @param connected whether the device is connected.
+ * @return retval operation completion status.
+ */
+ setConnectedState(DeviceAddress address, bool connected)
+ generates (Result retval);
+
+ /**
+ * Sets the HW synchronization source. Calling this method is equivalent to
+ * setting AUDIO_PARAMETER_STREAM_HW_AV_SYNC on the legacy HAL.
+ * Optional method
+ *
+ * @param hwAvSync HW synchronization source
+ * @return retval operation completion status.
+ */
+ setHwAvSync(AudioHwSync hwAvSync) generates (Result retval);
+
+ /**
+ * Generic method for retrieving vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * Multiple parameters can be retrieved at the same time.
+ * The implementation should return as many requested parameters
+ * as possible, even if one or more is not supported
+ *
+ * @param context provides more information about the request
+ * @param keys keys of the requested parameters
+ * @return retval operation completion status.
+ * OK must be returned if keys is empty.
+ * NOT_SUPPORTED must be returned if at least one key is unknown.
+ * @return parameters parameter key value pairs.
+ * Must contain the value of all requested keys if retval == OK
+ */
+ getParameters(vec<ParameterValue> context, vec<string> keys)
+ generates (Result retval, vec<ParameterValue> parameters);
+
+ /**
+ * Generic method for setting vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * Multiple parameters can be set at the same time though this is
+ * discouraged as it make failure analysis harder.
+ *
+ * If possible, a failed setParameters should not impact the platform state.
+ *
+ * @param context provides more information about the request
+ * @param parameters parameter key value pairs.
+ * @return retval operation completion status.
+ * All parameters must be successfully set for OK to be returned
+ */
+ setParameters(vec<ParameterValue> context, vec<ParameterValue> parameters)
+ generates (Result retval);
+
+ /**
+ * Called by the framework to start a stream operating in mmap mode.
+ * createMmapBuffer() must be called before calling start().
+ * Function only implemented by streams operating in mmap mode.
+ *
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED on non mmap mode streams
+ * INVALID_STATE if called out of sequence
+ */
+ start() generates (Result retval);
+
+ /**
+ * Called by the framework to stop a stream operating in mmap mode.
+ * Function only implemented by streams operating in mmap mode.
+ *
+ * @return retval OK in case the succes.
+ * NOT_SUPPORTED on non mmap mode streams
+ * INVALID_STATE if called out of sequence
+ */
+ stop() generates (Result retval) ;
+
+ /**
+ * Called by the framework to retrieve information on the mmap buffer used for audio
+ * samples transfer.
+ * Function only implemented by streams operating in mmap mode.
+ *
+ * @param minSizeFrames minimum buffer size requested. The actual buffer
+ * size returned in struct MmapBufferInfo can be larger.
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED on non mmap mode streams
+ * NOT_INITIALIZED in case of memory allocation error
+ * INVALID_ARGUMENTS if the requested buffer size is too large
+ * INVALID_STATE if called out of sequence
+ * @return info a MmapBufferInfo struct containing information on the MMMAP buffer created.
+ */
+ createMmapBuffer(int32_t minSizeFrames)
+ generates (Result retval, MmapBufferInfo info);
+
+ /**
+ * Called by the framework to read current read/write position in the mmap buffer
+ * with associated time stamp.
+ * Function only implemented by streams operating in mmap mode.
+ *
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED on non mmap mode streams
+ * INVALID_STATE if called out of sequence
+ * @return position a MmapPosition struct containing current HW read/write position in frames
+ * with associated time stamp.
+ */
+ getMmapPosition()
+ generates (Result retval, MmapPosition position);
+
+ /**
+ * Called by the framework to deinitialize the stream and free up
+ * all the currently allocated resources. It is recommended to close
+ * the stream on the client side as soon as it is becomes unused.
+ *
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED if called on IStream instead of input or
+ * output stream interface.
+ * INVALID_STATE if the stream was already closed.
+ */
+ close() generates (Result retval);
+};
diff --git a/audio/4.0/IStreamIn.hal b/audio/4.0/IStreamIn.hal
new file mode 100644
index 0000000..247e826
--- /dev/null
+++ b/audio/4.0/IStreamIn.hal
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IStream;
+
+interface IStreamIn extends IStream {
+ /**
+ * Returns the source descriptor of the input stream. Calling this method is
+ * equivalent to getting AUDIO_PARAMETER_STREAM_INPUT_SOURCE on the legacy
+ * HAL.
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return source audio source.
+ */
+ getAudioSource() generates (Result retval, AudioSource source);
+
+ /**
+ * Set the input gain for the audio driver.
+ * Optional method
+ *
+ * @param gain 1.0f is unity, 0.0f is zero.
+ * @result retval operation completion status.
+ */
+ setGain(float gain) generates (Result retval);
+
+ /**
+ * Commands that can be executed on the driver reader thread.
+ */
+ enum ReadCommand : int32_t {
+ READ,
+ GET_CAPTURE_POSITION
+ };
+
+ /**
+ * Data structure passed to the driver for executing commands
+ * on the driver reader thread.
+ */
+ struct ReadParameters {
+ ReadCommand command; // discriminator
+ union Params {
+ uint64_t read; // READ command, amount of bytes to read, >= 0.
+ // No parameters for GET_CAPTURE_POSITION.
+ } params;
+ };
+
+ /**
+ * Data structure passed back to the client via status message queue
+ * of 'read' operation.
+ *
+ * Possible values of 'retval' field:
+ * - OK, read operation was successful;
+ * - INVALID_ARGUMENTS, stream was not configured properly;
+ * - INVALID_STATE, stream is in a state that doesn't allow reads.
+ */
+ struct ReadStatus {
+ Result retval;
+ ReadCommand replyTo; // discriminator
+ union Reply {
+ uint64_t read; // READ command, amount of bytes read, >= 0.
+ struct CapturePosition { // same as generated by getCapturePosition.
+ uint64_t frames;
+ uint64_t time;
+ } capturePosition;
+ } reply;
+ };
+
+ /**
+ * Called when the metadata of the stream's sink has been changed.
+ * @param sinkMetadata Description of the audio that is suggested by the clients.
+ */
+ updateSinkMetadata(SinkMetadata sinkMetadata);
+
+ /**
+ * Set up required transports for receiving audio buffers from the driver.
+ *
+ * The transport consists of three message queues:
+ * -- command queue is used to instruct the reader thread what operation
+ * to perform;
+ * -- data queue is used for passing audio data from the driver
+ * to the client;
+ * -- status queue is used for reporting operation status
+ * (e.g. amount of bytes actually read or error code).
+ *
+ * The driver operates on a dedicated thread. The client must ensure that
+ * the thread is given an appropriate priority and assigned to correct
+ * scheduler and cgroup. For this purpose, the method returns identifiers
+ * of the driver thread.
+ *
+ * @param frameSize the size of a single frame, in bytes.
+ * @param framesCount the number of frames in a buffer.
+ * @param threadPriority priority of the driver thread.
+ * @return retval OK if both message queues were created successfully.
+ * INVALID_STATE if the method was already called.
+ * INVALID_ARGUMENTS if there was a problem setting up
+ * the queues.
+ * @return commandMQ a message queue used for passing commands.
+ * @return dataMQ a message queue used for passing audio data in the format
+ * specified at the stream opening.
+ * @return statusMQ a message queue used for passing status from the driver
+ * using ReadStatus structures.
+ * @return threadInfo identifiers of the driver's dedicated thread.
+ */
+ prepareForReading(uint32_t frameSize, uint32_t framesCount)
+ generates (
+ Result retval,
+ fmq_sync<ReadParameters> commandMQ,
+ fmq_sync<uint8_t> dataMQ,
+ fmq_sync<ReadStatus> statusMQ,
+ ThreadInfo threadInfo);
+
+ /**
+ * Return the amount of input frames lost in the audio driver since the last
+ * call of this function.
+ *
+ * Audio driver is expected to reset the value to 0 and restart counting
+ * upon returning the current value by this function call. Such loss
+ * typically occurs when the user space process is blocked longer than the
+ * capacity of audio driver buffers.
+ *
+ * @return framesLost the number of input audio frames lost.
+ */
+ getInputFramesLost() generates (uint32_t framesLost);
+
+ /**
+ * Return a recent count of the number of audio frames received and the
+ * clock time associated with that frame count.
+ *
+ * @return retval INVALID_STATE if the device is not ready/available,
+ * NOT_SUPPORTED if the command is not supported,
+ * OK otherwise.
+ * @return frames the total frame count received. This must be as early in
+ * the capture pipeline as possible. In general, frames
+ * must be non-negative and must not go "backwards".
+ * @return time is the clock monotonic time when frames was measured. In
+ * general, time must be a positive quantity and must not
+ * go "backwards".
+ */
+ getCapturePosition()
+ generates (Result retval, uint64_t frames, uint64_t time);
+
+ /**
+ * Returns an array with active microphones in the stream.
+ *
+ * @return retval INVALID_STATE if the call is not successful,
+ * OK otherwise.
+ *
+ * @return microphones array with microphones info
+ */
+ getActiveMicrophones()
+ generates(Result retval, vec<MicrophoneInfo> microphones);
+};
diff --git a/audio/4.0/IStreamOut.hal b/audio/4.0/IStreamOut.hal
new file mode 100644
index 0000000..3aa93fc
--- /dev/null
+++ b/audio/4.0/IStreamOut.hal
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IStream;
+import IStreamOutCallback;
+
+interface IStreamOut extends IStream {
+ /**
+ * Return the audio hardware driver estimated latency in milliseconds.
+ *
+ * @return latencyMs latency in milliseconds.
+ */
+ getLatency() generates (uint32_t latencyMs);
+
+ /**
+ * This method is used in situations where audio mixing is done in the
+ * hardware. This method serves as a direct interface with hardware,
+ * allowing to directly set the volume as apposed to via the framework.
+ * This method might produce multiple PCM outputs or hardware accelerated
+ * codecs, such as MP3 or AAC.
+ * Optional method
+ *
+ * @param left left channel attenuation, 1.0f is unity, 0.0f is zero.
+ * @param right right channel attenuation, 1.0f is unity, 0.0f is zero.
+ * @return retval operation completion status.
+ * If a volume is outside [0,1], return INVALID_ARGUMENTS
+ */
+ setVolume(float left, float right) generates (Result retval);
+
+ /**
+ * Commands that can be executed on the driver writer thread.
+ */
+ enum WriteCommand : int32_t {
+ WRITE,
+ GET_PRESENTATION_POSITION,
+ GET_LATENCY
+ };
+
+ /**
+ * Data structure passed back to the client via status message queue
+ * of 'write' operation.
+ *
+ * Possible values of 'retval' field:
+ * - OK, write operation was successful;
+ * - INVALID_ARGUMENTS, stream was not configured properly;
+ * - INVALID_STATE, stream is in a state that doesn't allow writes;
+ * - INVALID_OPERATION, retrieving presentation position isn't supported.
+ */
+ struct WriteStatus {
+ Result retval;
+ WriteCommand replyTo; // discriminator
+ union Reply {
+ uint64_t written; // WRITE command, amount of bytes written, >= 0.
+ struct PresentationPosition { // same as generated by
+ uint64_t frames; // getPresentationPosition.
+ TimeSpec timeStamp;
+ } presentationPosition;
+ uint32_t latencyMs; // Same as generated by getLatency.
+ } reply;
+ };
+
+ /**
+ * Called when the metadata of the stream's source has been changed.
+ * @param sourceMetadata Description of the audio that is played by the clients.
+ */
+ updateSourceMetadata(SourceMetadata sourceMetadata);
+
+ /**
+ * Set up required transports for passing audio buffers to the driver.
+ *
+ * The transport consists of three message queues:
+ * -- command queue is used to instruct the writer thread what operation
+ * to perform;
+ * -- data queue is used for passing audio data from the client
+ * to the driver;
+ * -- status queue is used for reporting operation status
+ * (e.g. amount of bytes actually written or error code).
+ *
+ * The driver operates on a dedicated thread. The client must ensure that
+ * the thread is given an appropriate priority and assigned to correct
+ * scheduler and cgroup. For this purpose, the method returns identifiers
+ * of the driver thread.
+ *
+ * @param frameSize the size of a single frame, in bytes.
+ * @param framesCount the number of frames in a buffer.
+ * @return retval OK if both message queues were created successfully.
+ * INVALID_STATE if the method was already called.
+ * INVALID_ARGUMENTS if there was a problem setting up
+ * the queues.
+ * @return commandMQ a message queue used for passing commands.
+ * @return dataMQ a message queue used for passing audio data in the format
+ * specified at the stream opening.
+ * @return statusMQ a message queue used for passing status from the driver
+ * using WriteStatus structures.
+ * @return threadInfo identifiers of the driver's dedicated thread.
+ */
+ prepareForWriting(uint32_t frameSize, uint32_t framesCount)
+ generates (
+ Result retval,
+ fmq_sync<WriteCommand> commandMQ,
+ fmq_sync<uint8_t> dataMQ,
+ fmq_sync<WriteStatus> statusMQ,
+ ThreadInfo threadInfo);
+
+ /**
+ * Return the number of audio frames written by the audio DSP to DAC since
+ * the output has exited standby.
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return dspFrames number of audio frames written.
+ */
+ getRenderPosition() generates (Result retval, uint32_t dspFrames);
+
+ /**
+ * Get the local time at which the next write to the audio driver will be
+ * presented. The units are microseconds, where the epoch is decided by the
+ * local audio HAL.
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return timestampUs time of the next write.
+ */
+ getNextWriteTimestamp() generates (Result retval, int64_t timestampUs);
+
+ /**
+ * Set the callback interface for notifying completion of non-blocking
+ * write and drain.
+ *
+ * Calling this function implies that all future 'write' and 'drain'
+ * must be non-blocking and use the callback to signal completion.
+ *
+ * 'clearCallback' method needs to be called in order to release the local
+ * callback proxy on the server side and thus dereference the callback
+ * implementation on the client side.
+ *
+ * @return retval operation completion status.
+ */
+ setCallback(IStreamOutCallback callback) generates (Result retval);
+
+ /**
+ * Clears the callback previously set via 'setCallback' method.
+ *
+ * Warning: failure to call this method results in callback implementation
+ * on the client side being held until the HAL server termination.
+ *
+ * If no callback was previously set, the method should be a no-op
+ * and return OK.
+ *
+ * @return retval operation completion status: OK or NOT_SUPPORTED.
+ */
+ clearCallback() generates (Result retval);
+
+ /**
+ * Returns whether HAL supports pausing and resuming of streams.
+ *
+ * @return supportsPause true if pausing is supported.
+ * @return supportsResume true if resume is supported.
+ */
+ supportsPauseAndResume()
+ generates (bool supportsPause, bool supportsResume);
+
+ /**
+ * Notifies to the audio driver to stop playback however the queued buffers
+ * are retained by the hardware. Useful for implementing pause/resume. Empty
+ * implementation if not supported however must be implemented for hardware
+ * with non-trivial latency. In the pause state, some audio hardware may
+ * still be using power. Client code may consider calling 'suspend' after a
+ * timeout to prevent that excess power usage.
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ *
+ * @return retval operation completion status.
+ */
+ pause() generates (Result retval);
+
+ /**
+ * Notifies to the audio driver to resume playback following a pause.
+ * Returns error INVALID_STATE if called without matching pause.
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ *
+ * @return retval operation completion status.
+ */
+ resume() generates (Result retval);
+
+ /**
+ * Returns whether HAL supports draining of streams.
+ *
+ * @return supports true if draining is supported.
+ */
+ supportsDrain() generates (bool supports);
+
+ /**
+ * Requests notification when data buffered by the driver/hardware has been
+ * played. If 'setCallback' has previously been called to enable
+ * non-blocking mode, then 'drain' must not block, instead it must return
+ * quickly and completion of the drain is notified through the callback. If
+ * 'setCallback' has not been called, then 'drain' must block until
+ * completion.
+ *
+ * If 'type' is 'ALL', the drain completes when all previously written data
+ * has been played.
+ *
+ * If 'type' is 'EARLY_NOTIFY', the drain completes shortly before all data
+ * for the current track has played to allow time for the framework to
+ * perform a gapless track switch.
+ *
+ * Drain must return immediately on 'stop' and 'flush' calls.
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ *
+ * @param type type of drain.
+ * @return retval operation completion status.
+ */
+ drain(AudioDrain type) generates (Result retval);
+
+ /**
+ * Notifies to the audio driver to flush the queued data. Stream must
+ * already be paused before calling 'flush'.
+ * Optional method
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ *
+ * @return retval operation completion status.
+ */
+ flush() generates (Result retval);
+
+ /**
+ * Return a recent count of the number of audio frames presented to an
+ * external observer. This excludes frames which have been written but are
+ * still in the pipeline. The count is not reset to zero when output enters
+ * standby. Also returns the value of CLOCK_MONOTONIC as of this
+ * presentation count. The returned count is expected to be 'recent', but
+ * does not need to be the most recent possible value. However, the
+ * associated time must correspond to whatever count is returned.
+ *
+ * Example: assume that N+M frames have been presented, where M is a 'small'
+ * number. Then it is permissible to return N instead of N+M, and the
+ * timestamp must correspond to N rather than N+M. The terms 'recent' and
+ * 'small' are not defined. They reflect the quality of the implementation.
+ *
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return frames count of presented audio frames.
+ * @return timeStamp associated clock time.
+ */
+ getPresentationPosition()
+ generates (Result retval, uint64_t frames, TimeSpec timeStamp);
+};
diff --git a/audio/4.0/IStreamOutCallback.hal b/audio/4.0/IStreamOutCallback.hal
new file mode 100644
index 0000000..9a19d32
--- /dev/null
+++ b/audio/4.0/IStreamOutCallback.hal
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio@4.0;
+
+/**
+ * Asynchronous write callback interface.
+ */
+interface IStreamOutCallback {
+ /**
+ * Non blocking write completed.
+ */
+ oneway onWriteReady();
+
+ /**
+ * Drain completed.
+ */
+ oneway onDrainReady();
+
+ /**
+ * Stream hit an error.
+ */
+ oneway onError();
+};
diff --git a/audio/4.0/config/audio_policy_configuration.xsd b/audio/4.0/config/audio_policy_configuration.xsd
new file mode 100644
index 0000000..924fb47
--- /dev/null
+++ b/audio/4.0/config/audio_policy_configuration.xsd
@@ -0,0 +1,594 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<!-- TODO: define a targetNamespace. Note that it will break retrocompatibility -->
+<xs:schema version="2.0"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <!-- List the config versions supported by audio policy. -->
+ <xs:simpleType name="version">
+ <xs:restriction base="xs:decimal">
+ <xs:enumeration value="1.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="halVersion">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Version of the interface the hal implements.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:decimal">
+ <!-- List of HAL versions supported by the framework. -->
+ <xs:enumeration value="2.0"/>
+ <xs:enumeration value="3.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="audioPolicyConfiguration">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="globalConfiguration" type="globalConfiguration"/>
+ <xs:element name="modules" type="modules" maxOccurs="unbounded"/>
+ <xs:element name="volumes" type="volumes" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="version" type="version"/>
+ </xs:complexType>
+ <xs:key name="moduleNameKey">
+ <xs:selector xpath="modules/module"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:unique name="volumeTargetUniqueness">
+ <xs:selector xpath="volumes/volume"/>
+ <xs:field xpath="@stream"/>
+ <xs:field xpath="@deviceCategory"/>
+ </xs:unique>
+ <xs:key name="volumeCurveNameKey">
+ <xs:selector xpath="volumes/reference"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:keyref name="volumeCurveRef" refer="volumeCurveNameKey">
+ <xs:selector xpath="volumes/volume"/>
+ <xs:field xpath="@ref"/>
+ </xs:keyref>
+ </xs:element>
+ <xs:complexType name="globalConfiguration">
+ <xs:attribute name="speaker_drc_enabled" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ <!-- Enum values of IDevicesFactory::Device
+ TODO: generate from hidl to avoid manual sync. -->
+ <xs:simpleType name="halName">
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="primary"/>
+ <xs:enumeration value="a2dp"/>
+ <xs:enumeration value="usb"/>
+ <xs:enumeration value="r_submix"/>
+ <xs:enumeration value="codec_offload"/>
+ <xs:enumeration value="stub"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Vendor eXtension names must be in the vx namespace.
+ Vendor are encouraged to namespace their module names.
+ Example for an hypothetical Google virtual reality HAL:
+ <module name="vx_google_vr" halVersion="3.0"/>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="vx_[_a-zA-Z0-9]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:complexType name="modules">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ There should be one section per audio HW module present on the platform.
+ Each <module/> contains two mandatory tags: “halVersion” and “name”.
+ The module "name" is the same as in previous .conf file.
+ Each module must contain the following sections:
+ - <devicePorts/>: a list of device descriptors for all
+ input and output devices accessible via this module.
+ This contains both permanently attached devices and removable devices.
+ - <mixPorts/>: listing all output and input streams exposed by the audio HAL
+ - <routes/>: list of possible connections between input
+ and output devices or between stream and devices.
+ A <route/> is defined by a set of 3 attributes:
+ -"type": mux|mix means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via this route
+ - <attachedDevices/>: permanently attached devices.
+ The attachedDevices section is a list of devices names.
+ Their names correspond to device names defined in "devicePorts" section.
+ - <defaultOutputDevice/> is the device to be used when no policy rule applies
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="module" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="attachedDevices" type="attachedDevices" minOccurs="0">
+ <xs:unique name="attachedDevicesUniqueness">
+ <xs:selector xpath="item"/>
+ <xs:field xpath="."/>
+ </xs:unique>
+ </xs:element>
+ <xs:element name="defaultOutputDevice" type="xs:token" minOccurs="0"/>
+ <xs:element name="mixPorts" type="mixPorts" minOccurs="0"/>
+ <xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
+ <xs:element name="routes" type="routes" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="halName" use="required"/>
+ <xs:attribute name="halVersion" type="halVersion" use="required"/>
+ </xs:complexType>
+ <xs:unique name="mixPortNameUniqueness">
+ <xs:selector xpath="mixPorts/mixPort"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ <xs:key name="devicePortNameKey">
+ <xs:selector xpath="devicePorts/devicePort"/>
+ <xs:field xpath="@tagName"/>
+ </xs:key>
+ <xs:unique name="devicePortUniqueness">
+ <xs:selector xpath="devicePorts/devicePort"/>
+ <xs:field xpath="@type"/>
+ <xs:field xpath="@address"/>
+ </xs:unique>
+ <xs:keyref name="defaultOutputDeviceRef" refer="devicePortNameKey">
+ <xs:selector xpath="defaultOutputDevice"/>
+ <xs:field xpath="."/>
+ </xs:keyref>
+ <xs:keyref name="attachedDeviceRef" refer="devicePortNameKey">
+ <xs:selector xpath="attachedDevices/item"/>
+ <xs:field xpath="."/>
+ </xs:keyref>
+ <!-- The following 3 constraints try to make sure each sink port
+ is reference in one an only one route. -->
+ <xs:key name="routeSinkKey">
+ <!-- predicate [@type='sink'] does not work in xsd 1.0 -->
+ <xs:selector xpath="devicePorts/devicePort|mixPorts/mixPort"/>
+ <xs:field xpath="@tagName|@name"/>
+ </xs:key>
+ <xs:keyref name="routeSinkRef" refer="routeSinkKey">
+ <xs:selector xpath="routes/route"/>
+ <xs:field xpath="@sink"/>
+ </xs:keyref>
+ <xs:unique name="routeUniqueness">
+ <xs:selector xpath="routes/route"/>
+ <xs:field xpath="@sink"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="attachedDevices">
+ <xs:sequence>
+ <xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- TODO: separate values by space for better xsd validations. -->
+ <xs:simpleType name="audioInOutFlags">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ "|" separated list of audio_output_flags_t or audio_input_flags_t.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="|[_A-Z]+(\|[_A-Z]+)*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="role">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="sink"/>
+ <xs:enumeration value="source"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="mixPorts">
+ <xs:sequence>
+ <xs:element name="mixPort" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="gains" type="gains" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ <xs:attribute name="role" type="role" use="required"/>
+ <xs:attribute name="flags" type="audioInOutFlags"/>
+ <xs:attribute name="maxOpenCount" type="xs:unsignedInt"/>
+ <xs:attribute name="maxActiveCount" type="xs:unsignedInt"/>
+ <xs:attribute name="preferredUsage" type="audioUsageList">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ When choosing the mixPort of an audio track, the audioPolicy
+ first considers the mixPorts with a preferredUsage including
+ the track AudioUsage preferred .
+ If non support the track format, the other mixPorts are considered.
+ Eg: a <mixPort preferredUsage="AUDIO_USAGE_MEDIA" /> will receive
+ the audio of all apps playing with a MEDIA usage.
+ It may receive audio from ALARM if there are no audio compatible
+ <mixPort preferredUsage="AUDIO_USAGE_ALARM" />.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ <xs:unique name="mixPortProfileUniqueness">
+ <xs:selector xpath="profile"/>
+ <xs:field xpath="format"/>
+ <xs:field xpath="samplingRate"/>
+ <xs:field xpath="channelMasks"/>
+ </xs:unique>
+ <xs:unique name="mixPortGainUniqueness">
+ <xs:selector xpath="gains/gain"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- Enum values of audio_device_t in audio.h
+ TODO: generate from hidl to avoid manual sync.
+ TODO: separate source and sink in the xml for better xsd validations. -->
+ <xs:simpleType name="audioDevice">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_DEVICE_NONE"/>
+
+ <xs:enumeration value="AUDIO_DEVICE_OUT_EARPIECE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ALL_SCO"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ALL_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ALL_USB"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_TELEPHONY_TX"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_FM"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_DEFAULT"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_STUB"/>
+
+ <!-- Due to the xml format, IN types can not be a separated from OUT types -->
+ <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AMBIENT"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ALL_SCO"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ALL_USB"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- Enum values of audio_format_t in audio.h
+ TODO: generate from hidl to avoid manual sync. -->
+ <xs:simpleType name="audioFormat">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_FORMAT_PCM_16_BIT" />
+ <xs:enumeration value="AUDIO_FORMAT_PCM_8_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_32_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_8_24_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_FLOAT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_24_BIT_PACKED"/>
+ <xs:enumeration value="AUDIO_FORMAT_MP3"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_NB"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_WB"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_MAIN"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_SSR"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LTP"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_SCALABLE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ERLC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ELD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_MAIN"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SSR"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LTP"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SCALABLE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ERLC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ELD"/>
+ <xs:enumeration value="AUDIO_FORMAT_VORBIS"/>
+ <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_OPUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_AC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_E_AC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS_HD"/>
+ <xs:enumeration value="AUDIO_FORMAT_IEC61937"/>
+ <xs:enumeration value="AUDIO_FORMAT_DOLBY_TRUEHD"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRC"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCB"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCWB"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCNW"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADIF"/>
+ <xs:enumeration value="AUDIO_FORMAT_WMA"/>
+ <xs:enumeration value="AUDIO_FORMAT_WMA_PRO"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_WB_PLUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_MP2"/>
+ <xs:enumeration value="AUDIO_FORMAT_QCELP"/>
+ <xs:enumeration value="AUDIO_FORMAT_DSD"/>
+ <xs:enumeration value="AUDIO_FORMAT_FLAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_ALAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_APE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS"/>
+ <xs:enumeration value="AUDIO_FORMAT_SBC"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AC4"/>
+ <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- Enum values of audio::common::4_0::AudioUsage
+ TODO: generate from HIDL to avoid manual sync. -->
+ <xs:simpleType name="audioUsage">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_USAGE_UNKNOWN" />
+ <xs:enumeration value="AUDIO_USAGE_MEDIA" />
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+ <xs:enumeration value="AUDIO_USAGE_ALARM" />
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <xs:enumeration value="AUDIO_USAGE_GAME" />
+ <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANT" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioUsageList">
+ <xs:list itemType="audioUsage"/>
+ </xs:simpleType>
+ <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+ <xs:simpleType name="samplingRates">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]+(,[0-9]+)*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+ <xs:simpleType name="channelMask">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Comma (",") separated list of channel flags
+ from audio_channel_mask_t.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[_A-Z][_A-Z0-9]*(,[_A-Z][_A-Z0-9]*)*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="profile">
+ <xs:attribute name="name" type="xs:token" use="optional"/>
+ <xs:attribute name="format" type="audioFormat" use="optional"/>
+ <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+ <xs:attribute name="channelMasks" type="channelMask" use="optional"/>
+ </xs:complexType>
+ <xs:simpleType name="gainMode">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_GAIN_MODE_JOINT"/>
+ <xs:enumeration value="AUDIO_GAIN_MODE_CHANNELS"/>
+ <xs:enumeration value="AUDIO_GAIN_MODE_RAMP"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="gains">
+ <xs:sequence>
+ <xs:element name="gain" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ <xs:attribute name="mode" type="gainMode" use="required"/>
+ <xs:attribute name="channel_mask" type="channelMask" use="optional"/>
+ <xs:attribute name="minValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="maxValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="defaultValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
+ <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="devicePorts">
+ <xs:sequence>
+ <xs:element name="devicePort" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="gains" type="gains" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="tagName" type="xs:token" use="required"/>
+ <xs:attribute name="type" type="audioDevice" use="required"/>
+ <xs:attribute name="role" type="role" use="required"/>
+ <xs:attribute name="address" type="xs:string" use="optional" default=""/>
+ <!-- Note that XSD 1.0 can not check that a type only has one default. -->
+ <xs:attribute name="default" type="xs:boolean" use="optional">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ The default device will be used if multiple have the same type
+ and no explicit route request exists for a specific device of
+ that type.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ <xs:unique name="devicePortProfileUniqueness">
+ <xs:selector xpath="profile"/>
+ <xs:field xpath="format"/>
+ <xs:field xpath="samplingRate"/>
+ <xs:field xpath="channelMasks"/>
+ </xs:unique>
+ <xs:unique name="devicePortGainUniqueness">
+ <xs:selector xpath="gains/gain"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="mixType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="mix"/>
+ <xs:enumeration value="mux"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="routes">
+ <xs:sequence>
+ <xs:element name="route" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ List all available sources for a given sink.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="type" type="mixType" use="required"/>
+ <xs:attribute name="sink" type="xs:string" use="required"/>
+ <xs:attribute name="sources" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="volumes">
+ <xs:sequence>
+ <xs:element name="volume" type="volume" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="reference" type="reference" minOccurs="0" maxOccurs="unbounded">
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- TODO: Always require a ref for better xsd validations.
+ Currently a volume could have no points nor ref
+ as it can not be forbidden by xsd 1.0.-->
+ <xs:simpleType name="volumePoint">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Comma separated pair of number.
+ The fist one is the framework level (between 0 and 100).
+ The second one is the volume to send to the HAL.
+ The framework will interpolate volumes not specified.
+ Their MUST be at least 2 points specified.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="([0-9]{1,2}|100),-?[0-9]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- Enum values of audio_stream_type_t in audio-base.h
+ TODO: generate from hidl to avoid manual sync. -->
+ <xs:simpleType name="stream">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_STREAM_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_STREAM_SYSTEM"/>
+ <xs:enumeration value="AUDIO_STREAM_RING"/>
+ <xs:enumeration value="AUDIO_STREAM_MUSIC"/>
+ <xs:enumeration value="AUDIO_STREAM_ALARM"/>
+ <xs:enumeration value="AUDIO_STREAM_NOTIFICATION"/>
+ <xs:enumeration value="AUDIO_STREAM_BLUETOOTH_SCO"/>
+ <xs:enumeration value="AUDIO_STREAM_ENFORCED_AUDIBLE"/>
+ <xs:enumeration value="AUDIO_STREAM_DTMF"/>
+ <xs:enumeration value="AUDIO_STREAM_TTS"/>
+ <xs:enumeration value="AUDIO_STREAM_ACCESSIBILITY"/>
+ <xs:enumeration value="AUDIO_STREAM_REROUTING"/>
+ <xs:enumeration value="AUDIO_STREAM_PATCH"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- Enum values of device_category from Volume.h.
+ TODO: generate from hidl to avoid manual sync. -->
+ <xs:simpleType name="deviceCategory">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="DEVICE_CATEGORY_HEADSET"/>
+ <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
+ <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
+ <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="volume">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Volume section defines a volume curve for a given use case and device category.
+ It contains a list of points of this curve expressing the attenuation in Millibels
+ for a given volume index from 0 to 100.
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-9600</point>
+ <point>100,0</point>
+ </volume>
+
+ It may also reference a reference/@name to avoid duplicating curves.
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+ ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+ <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+ <point>0,-9600</point>
+ <point>100,0</point>
+ </reference>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="point" type="volumePoint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="stream" type="stream"/>
+ <xs:attribute name="deviceCategory" type="deviceCategory"/>
+ <xs:attribute name="ref" type="xs:token" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="reference">
+ <xs:sequence>
+ <xs:element name="point" type="volumePoint" minOccurs="2" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ </xs:complexType>
+</xs:schema>
diff --git a/audio/4.0/types.hal b/audio/4.0/types.hal
new file mode 100644
index 0000000..7853f3c
--- /dev/null
+++ b/audio/4.0/types.hal
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+
+enum Result : int32_t {
+ OK,
+ NOT_INITIALIZED,
+ INVALID_ARGUMENTS,
+ INVALID_STATE,
+ NOT_SUPPORTED
+};
+
+@export(name="audio_drain_type_t", value_prefix="AUDIO_DRAIN_")
+enum AudioDrain : int32_t {
+ /** drain() returns when all data has been played. */
+ ALL,
+ /**
+ * drain() returns a short time before all data from the current track has
+ * been played to give time for gapless track switch.
+ */
+ EARLY_NOTIFY
+};
+
+/**
+ * A substitute for POSIX timespec.
+ */
+struct TimeSpec {
+ uint64_t tvSec; // seconds
+ uint64_t tvNSec; // nanoseconds
+};
+
+/**
+ * IEEE 802 MAC address.
+ */
+typedef uint8_t[6] MacAddress;
+
+struct ParameterValue {
+ string key;
+ string value;
+};
+
+/**
+ * Specifies a device in case when several devices of the same type
+ * can be connected (e.g. BT A2DP, USB).
+ */
+struct DeviceAddress {
+ AudioDevice device; // discriminator
+ union Address {
+ MacAddress mac; // used for BLUETOOTH_A2DP_*
+ uint8_t[4] ipv4; // used for IP
+ struct Alsa {
+ int32_t card;
+ int32_t device;
+ } alsa; // used for USB_*
+ } address;
+ string busAddress; // used for BUS
+ string rSubmixAddress; // used for REMOTE_SUBMIX
+};
+
+enum MmapBufferFlag : uint32_t {
+ NONE = 0x0,
+ /**
+ * If the buffer can be securely shared to untrusted applications
+ * through the AAudio exclusive mode.
+ * Only set this flag if applications are restricted from accessing the
+ * memory surrounding the audio data buffer by a kernel mechanism.
+ * See Linux kernel's dma_buf.
+ */
+ APPLICATION_SHAREABLE = 0x1,
+};
+
+/**
+ * Mmap buffer descriptor returned by IStream.createMmapBuffer().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapBufferInfo {
+ /** Mmap memory buffer */
+ memory sharedMemory;
+ /** Total buffer size in frames */
+ uint32_t bufferSizeFrames;
+ /** Transfer size granularity in frames */
+ uint32_t burstSizeFrames;
+ /** Attributes describing the buffer. */
+ bitfield<MmapBufferFlag> flags;
+};
+
+/**
+ * Mmap buffer read/write position returned by IStream.getMmapPosition().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapPosition {
+ int64_t timeNanoseconds; // time stamp in ns, CLOCK_MONOTONIC
+ int32_t positionFrames; // increasing 32 bit frame count reset when IStream.stop() is called
+};
+
+/**
+ * The message queue flags used to synchronize reads and writes from
+ * message queues used by StreamIn and StreamOut.
+ */
+enum MessageQueueFlagBits : uint32_t {
+ NOT_EMPTY = 1 << 0,
+ NOT_FULL = 1 << 1
+};
+
+/** Metadata of a playback track for a StreamOut. */
+struct PlaybackTrackMetadata {
+ AudioUsage usage;
+ AudioContentType contentType;
+ /**
+ * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
+ * 2 means double amplification...
+ * Must not be negative.
+ */
+ float gain;
+};
+
+/** Metadatas of the source of a StreamOut. */
+struct SourceMetadata {
+ vec<PlaybackTrackMetadata> tracks;
+};
+
+/** Metadata of a record track for a StreamIn. */
+struct RecordTrackMetadata {
+ AudioSource source;
+ /**
+ * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
+ * 2 means double amplification...
+ * Must not be negative.
+ */
+ float gain;
+};
+
+/** Metadatas of the source of a StreamIn. */
+struct SinkMetadata {
+ vec<RecordTrackMetadata> tracks;
+};
+
+/*
+ * Microphone information
+ *
+ */
+
+/**
+ * A 3D point used to represent position or orientation of a microphone.
+ *
+ * Position: Coordinates of the microphone's capsule, in meters, from the
+ * bottom-left-back corner of the bounding box of android device in natural
+ * orientation (PORTRAIT for phones, LANDSCAPE for tablets, tvs, etc).
+ * The orientation musth match the reported by the api Display.getRotation().
+ *
+ * Orientation: Normalized vector to signal the main orientation of the
+ * microphone's capsule. Magnitude = sqrt(x^2 + y^2 + z^2) = 1
+ */
+struct AudioMicrophoneCoordinate {
+ float x;
+ float y;
+ float z;
+};
+
+/**
+ * Enum to identify the type of channel mapping for active microphones.
+ * Used channels further identify if the microphone has any significative
+ * process (e.g. High Pass Filtering, dynamic compression)
+ * Simple processing as constant gain adjustment must be DIRECT.
+ */
+enum AudioMicrophoneChannelMapping : uint32_t {
+ UNUSED = 0, /** Channel not used */
+ DIRECT = 1, /** Channel used and signal not processed */
+ PROCESSED = 2, /** Channel used and signal has some process */
+};
+
+/**
+ * Enum to identify locations of microphones in regards to the body of the
+ * android device.
+ */
+enum AudioMicrophoneLocation : uint32_t {
+ UNKNOWN = 0,
+ MAINBODY = 1,
+ MAINBODY_MOVABLE = 2,
+ PERIPHERAL = 3,
+};
+
+/**
+ * Identifier to help group related microphones together
+ * e.g. microphone arrays should belong to the same group
+ */
+typedef int32_t AudioMicrophoneGroup;
+
+/**
+ * Enum with standard polar patterns of microphones
+ */
+enum AudioMicrophoneDirectionality : uint32_t {
+ UNKNOWN = 0,
+ OMNI = 1,
+ BI_DIRECTIONAL = 2,
+ CARDIOID = 3,
+ HYPER_CARDIOID = 4,
+ SUPER_CARDIOID = 5,
+};
+
+/**
+ * A (frequency, level) pair. Used to represent frequency response.
+ */
+struct AudioFrequencyResponsePoint {
+ /** In Hz */
+ float frequency;
+ /** In dB */
+ float level;
+};
+
+/**
+ * Structure used by the HAL to describe microphone's characteristics
+ * Used by StreamIn and Device
+ */
+struct MicrophoneInfo {
+ /** Unique alphanumeric id for microphone. Guaranteed to be the same
+ * even after rebooting.
+ */
+ string deviceId;
+ /**
+ * Device specific information
+ */
+ DeviceAddress deviceAddress;
+ /** Each element of the vector must describe the channel with the same
+ * index.
+ */
+ vec<AudioMicrophoneChannelMapping> channelMapping;
+ /** Location of the microphone in regard to the body of the device */
+ AudioMicrophoneLocation location;
+ /** Identifier to help group related microphones together
+ * e.g. microphone arrays should belong to the same group
+ */
+ AudioMicrophoneGroup group;
+ /** Index of this microphone within the group.
+ * (group, index) must be unique within the same device.
+ */
+ uint32_t indexInTheGroup;
+ /** Level in dBFS produced by a 1000 Hz tone at 94 dB SPL */
+ float sensitivity;
+ /** Level in dB of the max SPL supported at 1000 Hz */
+ float maxSpl;
+ /** Level in dB of the min SPL supported at 1000 Hz */
+ float minSpl;
+ /** Standard polar pattern of the microphone */
+ AudioMicrophoneDirectionality directionality;
+ /** Vector with ordered frequency responses (from low to high frequencies)
+ * with the frequency response of the microphone.
+ * Levels are in dB, relative to level at 1000 Hz
+ */
+ vec<AudioFrequencyResponsePoint> frequencyResponse;
+ /** Position of the microphone's capsule in meters, from the
+ * bottom-left-back corner of the bounding box of device.
+ */
+ AudioMicrophoneCoordinate position;
+ /** Normalized point to signal the main orientation of the microphone's
+ * capsule. sqrt(x^2 + y^2 + z^2) = 1
+ */
+ AudioMicrophoneCoordinate orientation;
+};
diff --git a/audio/README b/audio/README
index 2b81450..1f1e8e3 100644
--- a/audio/README
+++ b/audio/README
@@ -1,8 +1,9 @@
Directory structure of the audio HIDL related code.
audio
-|-- 2.0 <== legacy 2.0 core HIDL (.hal) can not be moved to fit
-| the directory structure because already published
+|-- 2.0 <== HIDL (.hal) can not be moved to fit the directory structure
+| because that would create a separate HAL
+|-- 4.0 <== Version 4.0 of the core API
|
|-- common <== code common to audio core and effect API
| |-- 2.0
diff --git a/audio/common/4.0/Android.bp b/audio/common/4.0/Android.bp
new file mode 100644
index 0000000..9b737dc
--- /dev/null
+++ b/audio/common/4.0/Android.bp
@@ -0,0 +1,48 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.audio.common@4.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ ],
+ types: [
+ "AudioChannelMask",
+ "AudioConfig",
+ "AudioContentType",
+ "AudioDevice",
+ "AudioFormat",
+ "AudioGain",
+ "AudioGainConfig",
+ "AudioGainMode",
+ "AudioHandleConsts",
+ "AudioInputFlag",
+ "AudioMixLatencyClass",
+ "AudioMode",
+ "AudioOffloadInfo",
+ "AudioOutputFlag",
+ "AudioPort",
+ "AudioPortConfig",
+ "AudioPortConfigDeviceExt",
+ "AudioPortConfigMask",
+ "AudioPortConfigSessionExt",
+ "AudioPortDeviceExt",
+ "AudioPortMixExt",
+ "AudioPortRole",
+ "AudioPortSessionExt",
+ "AudioPortType",
+ "AudioSessionConsts",
+ "AudioSource",
+ "AudioStreamType",
+ "AudioUsage",
+ "FixedChannelCount",
+ "ThreadInfo",
+ "Uuid",
+ ],
+ gen_java: false,
+ gen_java_constants: true,
+}
+
diff --git a/audio/common/4.0/types.hal b/audio/common/4.0/types.hal
new file mode 100644
index 0000000..d4c6efe
--- /dev/null
+++ b/audio/common/4.0/types.hal
@@ -0,0 +1,888 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.common@4.0;
+
+/*
+ *
+ * IDs and Handles
+ *
+ */
+
+/**
+ * Handle type for identifying audio sources and sinks.
+ */
+typedef int32_t AudioIoHandle;
+
+/**
+ * Audio hw module handle functions or structures referencing a module.
+ */
+typedef int32_t AudioModuleHandle;
+
+/**
+ * Each port has a unique ID or handle allocated by policy manager.
+ */
+typedef int32_t AudioPortHandle;
+
+/**
+ * Each patch is identified by a handle at the interface used to create that
+ * patch. For instance, when a patch is created by the audio HAL, the HAL
+ * allocates and returns a handle. This handle is unique to a given audio HAL
+ * hardware module. But the same patch receives another system wide unique
+ * handle allocated by the framework. This unique handle is used for all
+ * transactions inside the framework.
+ */
+typedef int32_t AudioPatchHandle;
+
+/**
+ * A HW synchronization source returned by the audio HAL.
+ */
+typedef uint32_t AudioHwSync;
+
+/**
+ * Each port has a unique ID or handle allocated by policy manager.
+ */
+@export(name="")
+enum AudioHandleConsts : int32_t {
+ AUDIO_IO_HANDLE_NONE = 0,
+ AUDIO_MODULE_HANDLE_NONE = 0,
+ AUDIO_PORT_HANDLE_NONE = 0,
+ AUDIO_PATCH_HANDLE_NONE = 0,
+};
+
+/**
+ * Commonly used structure for passing unique identifieds (UUID).
+ * For the definition of UUID, refer to ITU-T X.667 spec.
+ */
+struct Uuid {
+ uint32_t timeLow;
+ uint16_t timeMid;
+ uint16_t versionAndTimeHigh;
+ uint16_t variantAndClockSeqHigh;
+ uint8_t[6] node;
+};
+
+
+/*
+ *
+ * Audio streams
+ *
+ */
+
+/**
+ * Audio stream type describing the intended use case of a stream.
+ */
+@export(name="audio_stream_type_t", value_prefix="AUDIO_STREAM_")
+enum AudioStreamType : int32_t {
+ // These values must kept in sync with
+ // frameworks/base/media/java/android/media/AudioSystem.java
+ DEFAULT = -1,
+ MIN = 0,
+ VOICE_CALL = 0,
+ SYSTEM = 1,
+ RING = 2,
+ MUSIC = 3,
+ ALARM = 4,
+ NOTIFICATION = 5,
+ BLUETOOTH_SCO = 6,
+ ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be
+ // routed to speaker
+ DTMF = 8,
+ TTS = 9, // Transmitted Through Speaker. Plays over speaker
+ // only, silent on other devices
+ ACCESSIBILITY = 10, // For accessibility talk back prompts
+ REROUTING = 11, // For dynamic policy output mixes
+ PATCH = 12, // For internal audio flinger tracks. Fixed volume
+};
+
+@export(name="audio_source_t", value_prefix="AUDIO_SOURCE_")
+enum AudioSource : int32_t {
+ // These values must kept in sync with
+ // frameworks/base/media/java/android/media/MediaRecorder.java,
+ // frameworks/av/services/audiopolicy/AudioPolicyService.cpp,
+ // system/media/audio_effects/include/audio_effects/audio_effects_conf.h
+ DEFAULT = 0,
+ MIC = 1,
+ VOICE_UPLINK = 2,
+ VOICE_DOWNLINK = 3,
+ VOICE_CALL = 4,
+ CAMCORDER = 5,
+ VOICE_RECOGNITION = 6,
+ VOICE_COMMUNICATION = 7,
+ /**
+ * Source for the mix to be presented remotely. An example of remote
+ * presentation is Wifi Display where a dongle attached to a TV can be used
+ * to play the mix captured by this audio source.
+ */
+ REMOTE_SUBMIX = 8,
+ /**
+ * Source for unprocessed sound. Usage examples include level measurement
+ * and raw signal analysis.
+ */
+ UNPROCESSED = 9,
+
+ FM_TUNER = 1998,
+};
+
+typedef int32_t AudioSession;
+/**
+ * Special audio session values.
+ */
+@export(name="audio_session_t", value_prefix="AUDIO_SESSION_")
+enum AudioSessionConsts : int32_t {
+ /**
+ * Session for effects attached to a particular output stream
+ * (value must be less than 0)
+ */
+ OUTPUT_STAGE = -1,
+ /**
+ * Session for effects applied to output mix. These effects can
+ * be moved by audio policy manager to another output stream
+ * (value must be 0)
+ */
+ OUTPUT_MIX = 0,
+ /**
+ * Application does not specify an explicit session ID to be used, and
+ * requests a new session ID to be allocated. Corresponds to
+ * AudioManager.AUDIO_SESSION_ID_GENERATE and
+ * AudioSystem.AUDIO_SESSION_ALLOCATE.
+ */
+ ALLOCATE = 0,
+ /**
+ * For use with AudioRecord::start(), this indicates no trigger session.
+ * It is also used with output tracks and patch tracks, which never have a
+ * session.
+ */
+ NONE = 0
+};
+
+/**
+ * Audio format is a 32-bit word that consists of:
+ * main format field (upper 8 bits)
+ * sub format field (lower 24 bits).
+ *
+ * The main format indicates the main codec type. The sub format field indicates
+ * options and parameters for each format. The sub format is mainly used for
+ * record to indicate for instance the requested bitrate or profile. It can
+ * also be used for certain formats to give informations not present in the
+ * encoded audio stream (e.g. octet alignement for AMR).
+ */
+@export(name="audio_format_t", value_prefix="AUDIO_FORMAT_")
+enum AudioFormat : uint32_t {
+ INVALID = 0xFFFFFFFFUL,
+ DEFAULT = 0,
+ PCM = 0x00000000UL,
+ MP3 = 0x01000000UL,
+ AMR_NB = 0x02000000UL,
+ AMR_WB = 0x03000000UL,
+ AAC = 0x04000000UL,
+ /** Deprecated, Use AAC_HE_V1 */
+ HE_AAC_V1 = 0x05000000UL,
+ /** Deprecated, Use AAC_HE_V2 */
+ HE_AAC_V2 = 0x06000000UL,
+ VORBIS = 0x07000000UL,
+ OPUS = 0x08000000UL,
+ AC3 = 0x09000000UL,
+ E_AC3 = 0x0A000000UL,
+ DTS = 0x0B000000UL,
+ DTS_HD = 0x0C000000UL,
+ /** IEC61937 is encoded audio wrapped in 16-bit PCM. */
+ IEC61937 = 0x0D000000UL,
+ DOLBY_TRUEHD = 0x0E000000UL,
+ EVRC = 0x10000000UL,
+ EVRCB = 0x11000000UL,
+ EVRCWB = 0x12000000UL,
+ EVRCNW = 0x13000000UL,
+ AAC_ADIF = 0x14000000UL,
+ WMA = 0x15000000UL,
+ WMA_PRO = 0x16000000UL,
+ AMR_WB_PLUS = 0x17000000UL,
+ MP2 = 0x18000000UL,
+ QCELP = 0x19000000UL,
+ DSD = 0x1A000000UL,
+ FLAC = 0x1B000000UL,
+ ALAC = 0x1C000000UL,
+ APE = 0x1D000000UL,
+ AAC_ADTS = 0x1E000000UL,
+ SBC = 0x1F000000UL,
+ APTX = 0x20000000UL,
+ APTX_HD = 0x21000000UL,
+ AC4 = 0x22000000UL,
+ LDAC = 0x23000000UL,
+ /** Dolby Metadata-enhanced Audio Transmission */
+ MAT = 0x24000000UL,
+ /** Deprecated */
+ MAIN_MASK = 0xFF000000UL,
+ SUB_MASK = 0x00FFFFFFUL,
+
+ /* Subformats */
+ PCM_SUB_16_BIT = 0x1, // PCM signed 16 bits
+ PCM_SUB_8_BIT = 0x2, // PCM unsigned 8 bits
+ PCM_SUB_32_BIT = 0x3, // PCM signed .31 fixed point
+ PCM_SUB_8_24_BIT = 0x4, // PCM signed 8.23 fixed point
+ PCM_SUB_FLOAT = 0x5, // PCM single-precision float pt
+ PCM_SUB_24_BIT_PACKED = 0x6, // PCM signed .23 fix pt (3 bytes)
+
+ MP3_SUB_NONE = 0x0,
+
+ AMR_SUB_NONE = 0x0,
+
+ AAC_SUB_MAIN = 0x1,
+ AAC_SUB_LC = 0x2,
+ AAC_SUB_SSR = 0x4,
+ AAC_SUB_LTP = 0x8,
+ AAC_SUB_HE_V1 = 0x10,
+ AAC_SUB_SCALABLE = 0x20,
+ AAC_SUB_ERLC = 0x40,
+ AAC_SUB_LD = 0x80,
+ AAC_SUB_HE_V2 = 0x100,
+ AAC_SUB_ELD = 0x200,
+ AAC_SUB_XHE = 0x300,
+
+ VORBIS_SUB_NONE = 0x0,
+
+ E_AC3_SUB_JOC = 0x1,
+
+ MAT_SUB_1_0 = 0x1,
+ MAT_SUB_2_0 = 0x2,
+ MAT_SUB_2_1 = 0x3,
+
+ /* Aliases */
+ /** note != AudioFormat.ENCODING_PCM_16BIT */
+ PCM_16_BIT = (PCM | PCM_SUB_16_BIT),
+ /** note != AudioFormat.ENCODING_PCM_8BIT */
+ PCM_8_BIT = (PCM | PCM_SUB_8_BIT),
+ PCM_32_BIT = (PCM | PCM_SUB_32_BIT),
+ PCM_8_24_BIT = (PCM | PCM_SUB_8_24_BIT),
+ PCM_FLOAT = (PCM | PCM_SUB_FLOAT),
+ PCM_24_BIT_PACKED = (PCM | PCM_SUB_24_BIT_PACKED),
+ AAC_MAIN = (AAC | AAC_SUB_MAIN),
+ AAC_LC = (AAC | AAC_SUB_LC),
+ AAC_SSR = (AAC | AAC_SUB_SSR),
+ AAC_LTP = (AAC | AAC_SUB_LTP),
+ AAC_HE_V1 = (AAC | AAC_SUB_HE_V1),
+ AAC_SCALABLE = (AAC | AAC_SUB_SCALABLE),
+ AAC_ERLC = (AAC | AAC_SUB_ERLC),
+ AAC_LD = (AAC | AAC_SUB_LD),
+ AAC_HE_V2 = (AAC | AAC_SUB_HE_V2),
+ AAC_ELD = (AAC | AAC_SUB_ELD),
+ AAC_XHE = (AAC | AAC_SUB_XHE),
+ AAC_ADTS_MAIN = (AAC_ADTS | AAC_SUB_MAIN),
+ AAC_ADTS_LC = (AAC_ADTS | AAC_SUB_LC),
+ AAC_ADTS_SSR = (AAC_ADTS | AAC_SUB_SSR),
+ AAC_ADTS_LTP = (AAC_ADTS | AAC_SUB_LTP),
+ AAC_ADTS_HE_V1 = (AAC_ADTS | AAC_SUB_HE_V1),
+ AAC_ADTS_SCALABLE = (AAC_ADTS | AAC_SUB_SCALABLE),
+ AAC_ADTS_ERLC = (AAC_ADTS | AAC_SUB_ERLC),
+ AAC_ADTS_LD = (AAC_ADTS | AAC_SUB_LD),
+ AAC_ADTS_HE_V2 = (AAC_ADTS | AAC_SUB_HE_V2),
+ AAC_ADTS_ELD = (AAC_ADTS | AAC_SUB_ELD),
+ AAC_ADTS_XHE = (AAC_ADTS | AAC_SUB_XHE),
+ E_AC3_JOC = (E_AC3 | E_AC3_SUB_JOC),
+ MAT_1_0 = (MAT | MAT_SUB_1_0),
+ MAT_2_0 = (MAT | MAT_SUB_2_0),
+ MAT_2_1 = (MAT | MAT_SUB_2_1),
+};
+
+/**
+ * Usage of these values highlights places in the code that use 2- or 8- channel
+ * assumptions.
+ */
+@export(name="")
+enum FixedChannelCount : int32_t {
+ FCC_2 = 2, // This is typically due to legacy implementation of stereo I/O
+ FCC_8 = 8 // This is typically due to audio mixer and resampler limitations
+};
+
+/**
+ * A channel mask per se only defines the presence or absence of a channel, not
+ * the order. See AUDIO_INTERLEAVE_* for the platform convention of order.
+ *
+ * AudioChannelMask is an opaque type and its internal layout should not be
+ * assumed as it may change in the future. Instead, always use functions
+ * to examine it.
+ *
+ * These are the current representations:
+ *
+ * REPRESENTATION_POSITION
+ * is a channel mask representation for position assignment. Each low-order
+ * bit corresponds to the spatial position of a transducer (output), or
+ * interpretation of channel (input). The user of a channel mask needs to
+ * know the context of whether it is for output or input. The constants
+ * OUT_* or IN_* apply to the bits portion. It is not permitted for no bits
+ * to be set.
+ *
+ * REPRESENTATION_INDEX
+ * is a channel mask representation for index assignment. Each low-order
+ * bit corresponds to a selected channel. There is no platform
+ * interpretation of the various bits. There is no concept of output or
+ * input. It is not permitted for no bits to be set.
+ *
+ * All other representations are reserved for future use.
+ *
+ * Warning: current representation distinguishes between input and output, but
+ * this will not the be case in future revisions of the platform. Wherever there
+ * is an ambiguity between input and output that is currently resolved by
+ * checking the channel mask, the implementer should look for ways to fix it
+ * with additional information outside of the mask.
+ */
+@export(name="", value_prefix="AUDIO_CHANNEL_")
+enum AudioChannelMask : uint32_t {
+ /** must be 0 for compatibility */
+ REPRESENTATION_POSITION = 0,
+ /** 1 is reserved for future use */
+ REPRESENTATION_INDEX = 2,
+ /* 3 is reserved for future use */
+
+ /** These can be a complete value of AudioChannelMask */
+ NONE = 0x0,
+ INVALID = 0xC0000000,
+
+ /*
+ * These can be the bits portion of an AudioChannelMask
+ * with representation REPRESENTATION_POSITION.
+ */
+
+ /** output channels */
+ OUT_FRONT_LEFT = 0x1,
+ OUT_FRONT_RIGHT = 0x2,
+ OUT_FRONT_CENTER = 0x4,
+ OUT_LOW_FREQUENCY = 0x8,
+ OUT_BACK_LEFT = 0x10,
+ OUT_BACK_RIGHT = 0x20,
+ OUT_FRONT_LEFT_OF_CENTER = 0x40,
+ OUT_FRONT_RIGHT_OF_CENTER = 0x80,
+ OUT_BACK_CENTER = 0x100,
+ OUT_SIDE_LEFT = 0x200,
+ OUT_SIDE_RIGHT = 0x400,
+ OUT_TOP_CENTER = 0x800,
+ OUT_TOP_FRONT_LEFT = 0x1000,
+ OUT_TOP_FRONT_CENTER = 0x2000,
+ OUT_TOP_FRONT_RIGHT = 0x4000,
+ OUT_TOP_BACK_LEFT = 0x8000,
+ OUT_TOP_BACK_CENTER = 0x10000,
+ OUT_TOP_BACK_RIGHT = 0x20000,
+ OUT_TOP_CENTER_LEFT = 0x40000,
+ OUT_TOP_CENTER_RIGHT = 0x80000,
+
+ OUT_MONO = OUT_FRONT_LEFT,
+ OUT_STEREO = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT),
+ OUT_2POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_LOW_FREQUENCY),
+ OUT_2POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT),
+ OUT_2POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT |
+ OUT_LOW_FREQUENCY),
+ OUT_3POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT |
+ OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT),
+ OUT_3POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT |
+ OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT |
+ OUT_LOW_FREQUENCY),
+ OUT_QUAD = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_BACK_LEFT | OUT_BACK_RIGHT),
+ OUT_QUAD_BACK = OUT_QUAD,
+ /** like OUT_QUAD_BACK with *_SIDE_* instead of *_BACK_* */
+ OUT_QUAD_SIDE = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
+ OUT_SURROUND = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_FRONT_CENTER | OUT_BACK_CENTER),
+ OUT_PENTA = (OUT_QUAD | OUT_FRONT_CENTER),
+ OUT_5POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+ OUT_BACK_LEFT | OUT_BACK_RIGHT),
+ OUT_5POINT1_BACK = OUT_5POINT1,
+ /** like OUT_5POINT1_BACK with *_SIDE_* instead of *_BACK_* */
+ OUT_5POINT1_SIDE = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+ OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
+ OUT_6POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+ OUT_BACK_LEFT | OUT_BACK_RIGHT |
+ OUT_BACK_CENTER),
+ /** matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND */
+ OUT_7POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+ OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+ OUT_BACK_LEFT | OUT_BACK_RIGHT |
+ OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
+ // Note that the 2.0 OUT_ALL* have been moved to helper functions
+
+ /* These are bits only, not complete values */
+
+ /** input channels */
+ IN_LEFT = 0x4,
+ IN_RIGHT = 0x8,
+ IN_FRONT = 0x10,
+ IN_BACK = 0x20,
+ IN_LEFT_PROCESSED = 0x40,
+ IN_RIGHT_PROCESSED = 0x80,
+ IN_FRONT_PROCESSED = 0x100,
+ IN_BACK_PROCESSED = 0x200,
+ IN_PRESSURE = 0x400,
+ IN_X_AXIS = 0x800,
+ IN_Y_AXIS = 0x1000,
+ IN_Z_AXIS = 0x2000,
+ IN_BACK_LEFT = 0x10000,
+ IN_BACK_RIGHT = 0x20000,
+ IN_CENTER = 0x40000,
+ IN_LOW_FREQUENCY = 0x100000,
+ IN_TOP_LEFT = 0x200000,
+ IN_TOP_RIGHT = 0x400000,
+
+ IN_VOICE_UPLINK = 0x4000,
+ IN_VOICE_DNLINK = 0x8000,
+
+ IN_MONO = IN_FRONT,
+ IN_STEREO = (IN_LEFT | IN_RIGHT),
+ IN_FRONT_BACK = (IN_FRONT | IN_BACK),
+ IN_6 = (IN_LEFT | IN_RIGHT |
+ IN_FRONT | IN_BACK |
+ IN_LEFT_PROCESSED | IN_RIGHT_PROCESSED),
+ IN_5POINT1 = (IN_LEFT | IN_CENTER | IN_RIGHT |
+ IN_BACK_LEFT | IN_BACK_RIGHT | IN_LOW_FREQUENCY),
+ IN_VOICE_UPLINK_MONO = (IN_VOICE_UPLINK | IN_MONO),
+ IN_VOICE_DNLINK_MONO = (IN_VOICE_DNLINK | IN_MONO),
+ IN_VOICE_CALL_MONO = (IN_VOICE_UPLINK_MONO |
+ IN_VOICE_DNLINK_MONO),
+ // Note that the 2.0 IN_ALL* have been moved to helper functions
+
+ COUNT_MAX = 30,
+ INDEX_HDR = REPRESENTATION_INDEX << COUNT_MAX,
+ INDEX_MASK_1 = INDEX_HDR | ((1 << 1) - 1),
+ INDEX_MASK_2 = INDEX_HDR | ((1 << 2) - 1),
+ INDEX_MASK_3 = INDEX_HDR | ((1 << 3) - 1),
+ INDEX_MASK_4 = INDEX_HDR | ((1 << 4) - 1),
+ INDEX_MASK_5 = INDEX_HDR | ((1 << 5) - 1),
+ INDEX_MASK_6 = INDEX_HDR | ((1 << 6) - 1),
+ INDEX_MASK_7 = INDEX_HDR | ((1 << 7) - 1),
+ INDEX_MASK_8 = INDEX_HDR | ((1 << 8) - 1)
+};
+
+/**
+ * Major modes for a mobile device. The current mode setting affects audio
+ * routing.
+ */
+@export(name="audio_mode_t", value_prefix="AUDIO_MODE_")
+enum AudioMode : int32_t {
+ NORMAL = 0,
+ RINGTONE = 1,
+ /** Calls handled by the telephony stack (Eg: PSTN). */
+ IN_CALL = 2,
+ /** Calls handled by apps (Eg: Hangout). */
+ IN_COMMUNICATION = 3,
+};
+
+@export(name="", value_prefix="AUDIO_DEVICE_")
+enum AudioDevice : uint64_t {
+ NONE = 0x0,
+ /** reserved bits */
+ BIT_IN = 0x80000000,
+ BIT_DEFAULT = 0x40000000,
+ /** output devices */
+ OUT_EARPIECE = 0x1,
+ OUT_SPEAKER = 0x2,
+ OUT_WIRED_HEADSET = 0x4,
+ OUT_WIRED_HEADPHONE = 0x8,
+ OUT_BLUETOOTH_SCO = 0x10,
+ OUT_BLUETOOTH_SCO_HEADSET = 0x20,
+ OUT_BLUETOOTH_SCO_CARKIT = 0x40,
+ OUT_BLUETOOTH_A2DP = 0x80,
+ OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
+ OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
+ OUT_AUX_DIGITAL = 0x400,
+ OUT_HDMI = OUT_AUX_DIGITAL,
+ /** uses an analog connection (multiplexed over the USB pins for instance) */
+ OUT_ANLG_DOCK_HEADSET = 0x800,
+ OUT_DGTL_DOCK_HEADSET = 0x1000,
+ /** USB accessory mode: Android device is USB device and dock is USB host */
+ OUT_USB_ACCESSORY = 0x2000,
+ /** USB host mode: Android device is USB host and dock is USB device */
+ OUT_USB_DEVICE = 0x4000,
+ OUT_REMOTE_SUBMIX = 0x8000,
+ /** Telephony voice TX path */
+ OUT_TELEPHONY_TX = 0x10000,
+ /** Analog jack with line impedance detected */
+ OUT_LINE = 0x20000,
+ /** HDMI Audio Return Channel */
+ OUT_HDMI_ARC = 0x40000,
+ /** S/PDIF out */
+ OUT_SPDIF = 0x80000,
+ /** FM transmitter out */
+ OUT_FM = 0x100000,
+ /** Line out for av devices */
+ OUT_AUX_LINE = 0x200000,
+ /** limited-output speaker device for acoustic safety */
+ OUT_SPEAKER_SAFE = 0x400000,
+ OUT_IP = 0x800000,
+ /** audio bus implemented by the audio system (e.g an MOST stereo channel) */
+ OUT_BUS = 0x1000000,
+ OUT_PROXY = 0x2000000,
+ OUT_USB_HEADSET = 0x4000000,
+ OUT_ECHO_CANCELLER = 0x10000000,
+ OUT_DEFAULT = BIT_DEFAULT,
+ // Note that the 2.0 OUT_ALL* have been moved to helper functions
+
+ /** input devices */
+ IN_COMMUNICATION = BIT_IN | 0x1,
+ IN_AMBIENT = BIT_IN | 0x2,
+ IN_BUILTIN_MIC = BIT_IN | 0x4,
+ IN_BLUETOOTH_SCO_HEADSET = BIT_IN | 0x8,
+ IN_WIRED_HEADSET = BIT_IN | 0x10,
+ IN_AUX_DIGITAL = BIT_IN | 0x20,
+ IN_HDMI = IN_AUX_DIGITAL,
+ /** Telephony voice RX path */
+ IN_VOICE_CALL = BIT_IN | 0x40,
+ IN_TELEPHONY_RX = IN_VOICE_CALL,
+ IN_BACK_MIC = BIT_IN | 0x80,
+ IN_REMOTE_SUBMIX = BIT_IN | 0x100,
+ IN_ANLG_DOCK_HEADSET = BIT_IN | 0x200,
+ IN_DGTL_DOCK_HEADSET = BIT_IN | 0x400,
+ IN_USB_ACCESSORY = BIT_IN | 0x800,
+ IN_USB_DEVICE = BIT_IN | 0x1000,
+ /** FM tuner input */
+ IN_FM_TUNER = BIT_IN | 0x2000,
+ /** TV tuner input */
+ IN_TV_TUNER = BIT_IN | 0x4000,
+ /** Analog jack with line impedance detected */
+ IN_LINE = BIT_IN | 0x8000,
+ /** S/PDIF in */
+ IN_SPDIF = BIT_IN | 0x10000,
+ IN_BLUETOOTH_A2DP = BIT_IN | 0x20000,
+ IN_LOOPBACK = BIT_IN | 0x40000,
+ IN_IP = BIT_IN | 0x80000,
+ /** audio bus implemented by the audio system (e.g an MOST stereo channel) */
+ IN_BUS = BIT_IN | 0x100000,
+ IN_PROXY = BIT_IN | 0x1000000,
+ IN_USB_HEADSET = BIT_IN | 0x2000000,
+ IN_BLUETOOTH_BLE = BIT_IN | 0x4000000,
+ IN_DEFAULT = BIT_IN | BIT_DEFAULT,
+
+ // Note that the 2.0 IN_ALL* have been moved to helper functions
+};
+
+/**
+ * The audio output flags serve two purposes:
+ *
+ * - when an AudioTrack is created they indicate a "wish" to be connected to an
+ * output stream with attributes corresponding to the specified flags;
+ *
+ * - when present in an output profile descriptor listed for a particular audio
+ * hardware module, they indicate that an output stream can be opened that
+ * supports the attributes indicated by the flags.
+ *
+ * The audio policy manager will try to match the flags in the request
+ * (when getOuput() is called) to an available output stream.
+ */
+@export(name="audio_output_flags_t", value_prefix="AUDIO_OUTPUT_FLAG_")
+enum AudioOutputFlag : int32_t {
+ NONE = 0x0, // no attributes
+ DIRECT = 0x1, // this output directly connects a track
+ // to one output stream: no software mixer
+ PRIMARY = 0x2, // this output is the primary output of the device. It is
+ // unique and must be present. It is opened by default and
+ // receives routing, audio mode and volume controls related
+ // to voice calls.
+ FAST = 0x4, // output supports "fast tracks", defined elsewhere
+ DEEP_BUFFER = 0x8, // use deep audio buffers
+ COMPRESS_OFFLOAD = 0x10, // offload playback of compressed streams to
+ // hardware codec
+ NON_BLOCKING = 0x20, // use non-blocking write
+ HW_AV_SYNC = 0x40, // output uses a hardware A/V sync
+ TTS = 0x80, // output for streams transmitted through speaker at a
+ // sample rate high enough to accommodate lower-range
+ // ultrasonic p/b
+ RAW = 0x100, // minimize signal processing
+ SYNC = 0x200, // synchronize I/O streams
+ IEC958_NONAUDIO = 0x400, // Audio stream contains compressed audio in SPDIF
+ // data bursts, not PCM.
+ DIRECT_PCM = 0x2000, // Audio stream containing PCM data that needs
+ // to pass through compress path for DSP post proc.
+ MMAP_NOIRQ = 0x4000, // output operates in MMAP no IRQ mode.
+ VOIP_RX = 0x8000, // preferred output for VoIP calls.
+ /** preferred output for call music */
+ INCALL_MUSIC = 0x10000,
+};
+
+/**
+ * The audio input flags are analogous to audio output flags.
+ * Currently they are used only when an AudioRecord is created,
+ * to indicate a preference to be connected to an input stream with
+ * attributes corresponding to the specified flags.
+ */
+@export(name="audio_input_flags_t", value_prefix="AUDIO_INPUT_FLAG_")
+enum AudioInputFlag : int32_t {
+ NONE = 0x0, // no attributes
+ FAST = 0x1, // prefer an input that supports "fast tracks"
+ HW_HOTWORD = 0x2, // prefer an input that captures from hw hotword source
+ RAW = 0x4, // minimize signal processing
+ SYNC = 0x8, // synchronize I/O streams
+ MMAP_NOIRQ = 0x10, // input operates in MMAP no IRQ mode.
+ VOIP_TX = 0x20, // preferred input for VoIP calls.
+ HW_AV_SYNC = 0x40, // input connected to an output that uses a hardware A/V sync
+};
+
+@export(name="audio_usage_t", value_prefix="AUDIO_USAGE_")
+enum AudioUsage : int32_t {
+ // These values must kept in sync with
+ // frameworks/base/media/java/android/media/AudioAttributes.java
+ // Note that not all framework values are exposed
+ UNKNOWN = 0,
+ MEDIA = 1,
+ VOICE_COMMUNICATION = 2,
+ VOICE_COMMUNICATION_SIGNALLING = 3,
+ ALARM = 4,
+ NOTIFICATION = 5,
+ NOTIFICATION_TELEPHONY_RINGTONE = 6,
+ ASSISTANCE_ACCESSIBILITY = 11,
+ ASSISTANCE_NAVIGATION_GUIDANCE = 12,
+ ASSISTANCE_SONIFICATION = 13,
+ GAME = 14,
+ VIRTUAL_SOURCE = 15,
+ ASSISTANT = 16,
+};
+
+/** Type of audio generated by an application. */
+@export(name="audio_content_type_t", value_prefix="AUDIO_CONTENT_TYPE_")
+enum AudioContentType : uint32_t {
+ UNKNOWN = 0,
+ SPEECH = 1,
+ MUSIC = 2,
+ MOVIE = 3,
+ SONIFICATION = 4,
+};
+
+/**
+ * Additional information about the stream passed to hardware decoders.
+ */
+struct AudioOffloadInfo {
+ uint32_t sampleRateHz;
+ bitfield<AudioChannelMask> channelMask;
+ AudioFormat format;
+ AudioStreamType streamType;
+ uint32_t bitRatePerSecond;
+ int64_t durationMicroseconds; // -1 if unknown
+ bool hasVideo;
+ bool isStreaming;
+ uint32_t bitWidth;
+ uint32_t bufferSize;
+ AudioUsage usage;
+};
+
+/**
+ * Commonly used audio stream configuration parameters.
+ */
+struct AudioConfig {
+ uint32_t sampleRateHz;
+ bitfield<AudioChannelMask> channelMask;
+ AudioFormat format;
+ AudioOffloadInfo offloadInfo;
+ uint64_t frameCount;
+};
+
+
+/*
+ *
+ * Volume control
+ *
+ */
+
+/**
+ * Type of gain control exposed by an audio port.
+ */
+@export(name="", value_prefix="AUDIO_GAIN_MODE_")
+enum AudioGainMode : uint32_t {
+ JOINT = 0x1, // supports joint channel gain control
+ CHANNELS = 0x2, // supports separate channel gain control
+ RAMP = 0x4 // supports gain ramps
+};
+
+/**
+ * An audio_gain struct is a representation of a gain stage.
+ * A gain stage is always attached to an audio port.
+ */
+struct AudioGain {
+ bitfield<AudioGainMode> mode;
+ bitfield<AudioChannelMask> channelMask; // channels which gain an be controlled
+ int32_t minValue; // minimum gain value in millibels
+ int32_t maxValue; // maximum gain value in millibels
+ int32_t defaultValue; // default gain value in millibels
+ uint32_t stepValue; // gain step in millibels
+ uint32_t minRampMs; // minimum ramp duration in ms
+ uint32_t maxRampMs; // maximum ramp duration in ms
+};
+
+/**
+ * The gain configuration structure is used to get or set the gain values of a
+ * given port.
+ */
+struct AudioGainConfig {
+ int32_t index; // index of the corresponding AudioGain in AudioPort.gains
+ AudioGainMode mode;
+ AudioChannelMask channelMask; // channels which gain value follows
+ /**
+ * 4 = sizeof(AudioChannelMask),
+ * 8 is not "FCC_8", so it won't need to be changed for > 8 channels.
+ * Gain values in millibels for each channel ordered from LSb to MSb in
+ * channel mask. The number of values is 1 in joint mode or
+ * popcount(channel_mask).
+ */
+ int32_t[4 * 8] values;
+ uint32_t rampDurationMs; // ramp duration in ms
+};
+
+
+/*
+ *
+ * Routing control
+ *
+ */
+
+/*
+ * Types defined here are used to describe an audio source or sink at internal
+ * framework interfaces (audio policy, patch panel) or at the audio HAL.
+ * Sink and sources are grouped in a concept of “audio port” representing an
+ * audio end point at the edge of the system managed by the module exposing
+ * the interface.
+ */
+
+/** Audio port role: either source or sink */
+@export(name="audio_port_role_t", value_prefix="AUDIO_PORT_ROLE_")
+enum AudioPortRole : int32_t {
+ NONE,
+ SOURCE,
+ SINK,
+};
+
+/**
+ * Audio port type indicates if it is a session (e.g AudioTrack), a mix (e.g
+ * PlaybackThread output) or a physical device (e.g OUT_SPEAKER)
+ */
+@export(name="audio_port_type_t", value_prefix="AUDIO_PORT_TYPE_")
+enum AudioPortType : int32_t {
+ NONE,
+ DEVICE,
+ MIX,
+ SESSION,
+};
+
+/**
+ * Extension for audio port configuration structure when the audio port is a
+ * hardware device.
+ */
+struct AudioPortConfigDeviceExt {
+ AudioModuleHandle hwModule; // module the device is attached to
+ AudioDevice type; // device type (e.g OUT_SPEAKER)
+ uint8_t[32] address; // device address. "" if N/A
+};
+
+/**
+ * Extension for audio port configuration structure when the audio port is an
+ * audio session.
+ */
+struct AudioPortConfigSessionExt {
+ AudioSession session;
+};
+
+/**
+ * Flags indicating which fields are to be considered in AudioPortConfig.
+ */
+@export(name="", value_prefix="AUDIO_PORT_CONFIG_")
+enum AudioPortConfigMask : uint32_t {
+ SAMPLE_RATE = 0x1,
+ CHANNEL_MASK = 0x2,
+ FORMAT = 0x4,
+ GAIN = 0x8,
+};
+
+/**
+ * Audio port configuration structure used to specify a particular configuration
+ * of an audio port.
+ */
+struct AudioPortConfig {
+ AudioPortHandle id;
+ bitfield<AudioPortConfigMask> configMask;
+ uint32_t sampleRateHz;
+ bitfield<AudioChannelMask> channelMask;
+ AudioFormat format;
+ AudioGainConfig gain;
+ AudioPortType type; // type is used as a discriminator for Ext union
+ AudioPortRole role; // role is used as a discriminator for UseCase union
+ union Ext {
+ AudioPortConfigDeviceExt device;
+ struct AudioPortConfigMixExt {
+ AudioModuleHandle hwModule; // module the stream is attached to
+ AudioIoHandle ioHandle; // I/O handle of the input/output stream
+ union UseCase {
+ AudioStreamType stream;
+ AudioSource source;
+ } useCase;
+ } mix;
+ AudioPortConfigSessionExt session;
+ } ext;
+};
+
+/**
+ * Extension for audio port structure when the audio port is a hardware device.
+ */
+struct AudioPortDeviceExt {
+ AudioModuleHandle hwModule; // module the device is attached to
+ AudioDevice type;
+ /** 32 byte string identifying the port. */
+ uint8_t[32] address;
+};
+
+/**
+ * Latency class of the audio mix.
+ */
+@export(name="audio_mix_latency_class_t", value_prefix="AUDIO_LATENCY_")
+enum AudioMixLatencyClass : int32_t {
+ LOW,
+ NORMAL
+};
+
+struct AudioPortMixExt {
+ AudioModuleHandle hwModule; // module the stream is attached to
+ AudioIoHandle ioHandle; // I/O handle of the stream
+ AudioMixLatencyClass latencyClass;
+};
+
+/**
+ * Extension for audio port structure when the audio port is an audio session.
+ */
+struct AudioPortSessionExt {
+ AudioSession session;
+};
+
+struct AudioPort {
+ AudioPortHandle id;
+ AudioPortRole role;
+ string name;
+ vec<uint32_t> sampleRates;
+ vec<bitfield<AudioChannelMask>> channelMasks;
+ vec<AudioFormat> formats;
+ vec<AudioGain> gains;
+ AudioPortConfig activeConfig; // current audio port configuration
+ AudioPortType type; // type is used as a discriminator
+ union Ext {
+ AudioPortDeviceExt device;
+ AudioPortMixExt mix;
+ AudioPortSessionExt session;
+ } ext;
+};
+
+struct ThreadInfo {
+ int64_t pid;
+ int64_t tid;
+};
diff --git a/audio/effect/4.0/Android.bp b/audio/effect/4.0/Android.bp
new file mode 100644
index 0000000..e7676a9
--- /dev/null
+++ b/audio/effect/4.0/Android.bp
@@ -0,0 +1,47 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.audio.effect@4.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IAcousticEchoCancelerEffect.hal",
+ "IAutomaticGainControlEffect.hal",
+ "IBassBoostEffect.hal",
+ "IDownmixEffect.hal",
+ "IEffect.hal",
+ "IEffectBufferProviderCallback.hal",
+ "IEffectsFactory.hal",
+ "IEnvironmentalReverbEffect.hal",
+ "IEqualizerEffect.hal",
+ "ILoudnessEnhancerEffect.hal",
+ "INoiseSuppressionEffect.hal",
+ "IPresetReverbEffect.hal",
+ "IVirtualizerEffect.hal",
+ "IVisualizerEffect.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio.common@4.0",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "AudioBuffer",
+ "EffectAuxChannelsConfig",
+ "EffectBufferAccess",
+ "EffectBufferConfig",
+ "EffectConfig",
+ "EffectConfigParameters",
+ "EffectDescriptor",
+ "EffectFeature",
+ "EffectFlags",
+ "EffectOffloadParameter",
+ "MessageQueueFlagBits",
+ "Result",
+ ],
+ gen_java: false,
+ gen_java_constants: true,
+}
+
diff --git a/audio/effect/4.0/IAcousticEchoCancelerEffect.hal b/audio/effect/4.0/IAcousticEchoCancelerEffect.hal
new file mode 100644
index 0000000..f495e6f
--- /dev/null
+++ b/audio/effect/4.0/IAcousticEchoCancelerEffect.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IAcousticEchoCancelerEffect extends IEffect {
+ /**
+ * Sets echo delay value in milliseconds.
+ */
+ setEchoDelay(uint32_t echoDelayMs) generates (Result retval);
+
+ /**
+ * Gets echo delay value in milliseconds.
+ */
+ getEchoDelay() generates (Result retval, uint32_t echoDelayMs);
+};
diff --git a/audio/effect/4.0/IAutomaticGainControlEffect.hal b/audio/effect/4.0/IAutomaticGainControlEffect.hal
new file mode 100644
index 0000000..d7fa04c
--- /dev/null
+++ b/audio/effect/4.0/IAutomaticGainControlEffect.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IAutomaticGainControlEffect extends IEffect {
+ /**
+ * Sets target level in millibels.
+ */
+ setTargetLevel(int16_t targetLevelMb) generates (Result retval);
+
+ /**
+ * Gets target level.
+ */
+ getTargetLevel() generates (Result retval, int16_t targetLevelMb);
+
+ /**
+ * Sets gain in the compression range in millibels.
+ */
+ setCompGain(int16_t compGainMb) generates (Result retval);
+
+ /**
+ * Gets gain in the compression range.
+ */
+ getCompGain() generates (Result retval, int16_t compGainMb);
+
+ /**
+ * Enables or disables limiter.
+ */
+ setLimiterEnabled(bool enabled) generates (Result retval);
+
+ /**
+ * Returns whether limiter is enabled.
+ */
+ isLimiterEnabled() generates (Result retval, bool enabled);
+
+ struct AllProperties {
+ int16_t targetLevelMb;
+ int16_t compGainMb;
+ bool limiterEnabled;
+ };
+
+ /**
+ * Sets all properties at once.
+ */
+ setAllProperties(AllProperties properties) generates (Result retval);
+
+ /**
+ * Gets all properties at once.
+ */
+ getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/4.0/IBassBoostEffect.hal b/audio/effect/4.0/IBassBoostEffect.hal
new file mode 100644
index 0000000..bd302f6
--- /dev/null
+++ b/audio/effect/4.0/IBassBoostEffect.hal
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IBassBoostEffect extends IEffect {
+ /**
+ * Returns whether setting bass boost strength is supported.
+ */
+ isStrengthSupported() generates (Result retval, bool strengthSupported);
+
+ enum StrengthRange : uint16_t {
+ MIN = 0,
+ MAX = 1000
+ };
+
+ /**
+ * Sets bass boost strength.
+ *
+ * @param strength strength of the effect. The valid range for strength
+ * strength is [0, 1000], where 0 per mille designates the
+ * mildest effect and 1000 per mille designates the
+ * strongest.
+ * @return retval operation completion status.
+ */
+ setStrength(uint16_t strength) generates (Result retval);
+
+ /**
+ * Gets virtualization strength.
+ */
+ getStrength() generates (Result retval, uint16_t strength);
+};
diff --git a/audio/effect/4.0/IDownmixEffect.hal b/audio/effect/4.0/IDownmixEffect.hal
new file mode 100644
index 0000000..3ce3a79
--- /dev/null
+++ b/audio/effect/4.0/IDownmixEffect.hal
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IDownmixEffect extends IEffect {
+ enum Type : int32_t {
+ STRIP, // throw away the extra channels
+ FOLD // mix the extra channels with FL/FR
+ };
+
+ /**
+ * Sets the current downmix preset.
+ */
+ setType(Type preset) generates (Result retval);
+
+ /**
+ * Gets the current downmix preset.
+ */
+ getType() generates (Result retval, Type preset);
+};
diff --git a/audio/effect/4.0/IEffect.hal b/audio/effect/4.0/IEffect.hal
new file mode 100644
index 0000000..d1d9496
--- /dev/null
+++ b/audio/effect/4.0/IEffect.hal
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffectBufferProviderCallback;
+
+interface IEffect {
+ /**
+ * Initialize effect engine--all configurations return to default.
+ *
+ * @return retval operation completion status.
+ */
+ @entry
+ init() generates (Result retval);
+
+ /**
+ * Apply new audio parameters configurations for input and output buffers.
+ * The provider callbacks may be empty, but in this case the buffer
+ * must be provided in the EffectConfig structure.
+ *
+ * @param config configuration descriptor.
+ * @param inputBufferProvider optional buffer provider reference.
+ * @param outputBufferProvider optional buffer provider reference.
+ * @return retval operation completion status.
+ */
+ setConfig(EffectConfig config,
+ IEffectBufferProviderCallback inputBufferProvider,
+ IEffectBufferProviderCallback outputBufferProvider)
+ generates (Result retval);
+
+ /**
+ * Reset the effect engine. Keep configuration but resets state and buffer
+ * content.
+ *
+ * @return retval operation completion status.
+ */
+ reset() generates (Result retval);
+
+ /**
+ * Enable processing.
+ *
+ * @return retval operation completion status.
+ */
+ @callflow(next={"prepareForProcessing"})
+ enable() generates (Result retval);
+
+ /**
+ * Disable processing.
+ *
+ * @return retval operation completion status.
+ */
+ @callflow(next={"close"})
+ disable() generates (Result retval);
+
+ /**
+ * Set the rendering device the audio output path is connected to. The
+ * effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its
+ * descriptor to receive this command when the device changes.
+ *
+ * Note: this method is only supported for effects inserted into
+ * the output chain.
+ *
+ * @param device output device specification.
+ * @return retval operation completion status.
+ */
+ setDevice(bitfield<AudioDevice> device) generates (Result retval);
+
+ /**
+ * Set and get volume. Used by audio framework to delegate volume control to
+ * effect engine. The effect implementation must set EFFECT_FLAG_VOLUME_CTRL
+ * flag in its descriptor to receive this command. The effect engine must
+ * return the volume that should be applied before the effect is
+ * processed. The overall volume (the volume actually applied by the effect
+ * engine multiplied by the returned value) should match the value indicated
+ * in the command.
+ *
+ * @param volumes vector containing volume for each channel defined in
+ * EffectConfig for output buffer expressed in 8.24 fixed
+ * point format.
+ * @return result updated volume values.
+ * @return retval operation completion status.
+ */
+ setAndGetVolume(vec<uint32_t> volumes)
+ generates (Result retval, vec<uint32_t> result);
+
+ /**
+ * Notify the effect of the volume change. The effect implementation must
+ * set EFFECT_FLAG_VOLUME_IND flag in its descriptor to receive this
+ * command.
+ *
+ * @param volumes vector containing volume for each channel defined in
+ * EffectConfig for output buffer expressed in 8.24 fixed
+ * point format.
+ * @return retval operation completion status.
+ */
+ volumeChangeNotification(vec<uint32_t> volumes)
+ generates (Result retval);
+
+ /**
+ * Set the audio mode. The effect implementation must set
+ * EFFECT_FLAG_AUDIO_MODE_IND flag in its descriptor to receive this command
+ * when the audio mode changes.
+ *
+ * @param mode desired audio mode.
+ * @return retval operation completion status.
+ */
+ setAudioMode(AudioMode mode) generates (Result retval);
+
+ /**
+ * Apply new audio parameters configurations for input and output buffers of
+ * reverse stream. An example of reverse stream is the echo reference
+ * supplied to an Acoustic Echo Canceler.
+ *
+ * @param config configuration descriptor.
+ * @param inputBufferProvider optional buffer provider reference.
+ * @param outputBufferProvider optional buffer provider reference.
+ * @return retval operation completion status.
+ */
+ setConfigReverse(EffectConfig config,
+ IEffectBufferProviderCallback inputBufferProvider,
+ IEffectBufferProviderCallback outputBufferProvider)
+ generates (Result retval);
+
+ /**
+ * Set the capture device the audio input path is connected to. The effect
+ * implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to
+ * receive this command when the device changes.
+ *
+ * Note: this method is only supported for effects inserted into
+ * the input chain.
+ *
+ * @param device input device specification.
+ * @return retval operation completion status.
+ */
+ setInputDevice(bitfield<AudioDevice> device) generates (Result retval);
+
+ /**
+ * Read audio parameters configurations for input and output buffers.
+ *
+ * @return retval operation completion status.
+ * @return config configuration descriptor.
+ */
+ getConfig() generates (Result retval, EffectConfig config);
+
+ /**
+ * Read audio parameters configurations for input and output buffers of
+ * reverse stream.
+ *
+ * @return retval operation completion status.
+ * @return config configuration descriptor.
+ */
+ getConfigReverse() generates (Result retval, EffectConfig config);
+
+ /**
+ * Queries for supported combinations of main and auxiliary channels
+ * (e.g. for a multi-microphone noise suppressor).
+ *
+ * @param maxConfigs maximum number of the combinations to return.
+ * @return retval absence of the feature support is indicated using
+ * NOT_SUPPORTED code. RESULT_TOO_BIG is returned if
+ * the number of supported combinations exceeds 'maxConfigs'.
+ * @return result list of configuration descriptors.
+ */
+ getSupportedAuxChannelsConfigs(uint32_t maxConfigs)
+ generates (Result retval, vec<EffectAuxChannelsConfig> result);
+
+ /**
+ * Retrieves the current configuration of main and auxiliary channels.
+ *
+ * @return retval absence of the feature support is indicated using
+ * NOT_SUPPORTED code.
+ * @return result configuration descriptor.
+ */
+ getAuxChannelsConfig()
+ generates (Result retval, EffectAuxChannelsConfig result);
+
+ /**
+ * Sets the current configuration of main and auxiliary channels.
+ *
+ * @return retval operation completion status; absence of the feature
+ * support is indicated using NOT_SUPPORTED code.
+ */
+ setAuxChannelsConfig(EffectAuxChannelsConfig config)
+ generates (Result retval);
+
+ /**
+ * Set the audio source the capture path is configured for (Camcorder, voice
+ * recognition...).
+ *
+ * Note: this method is only supported for effects inserted into
+ * the input chain.
+ *
+ * @param source source descriptor.
+ * @return retval operation completion status.
+ */
+ setAudioSource(AudioSource source) generates (Result retval);
+
+ /**
+ * This command indicates if the playback thread the effect is attached to
+ * is offloaded or not, and updates the I/O handle of the playback thread
+ * the effect is attached to.
+ *
+ * @param param effect offload descriptor.
+ * @return retval operation completion status.
+ */
+ offload(EffectOffloadParameter param) generates (Result retval);
+
+ /**
+ * Returns the effect descriptor.
+ *
+ * @return retval operation completion status.
+ * @return descriptor effect descriptor.
+ */
+ getDescriptor() generates (Result retval, EffectDescriptor descriptor);
+
+ /**
+ * Set up required transports for passing audio buffers to the effect.
+ *
+ * The transport consists of shared memory and a message queue for reporting
+ * effect processing operation status. The shared memory is set up
+ * separately using 'setProcessBuffers' method.
+ *
+ * Processing is requested by setting 'REQUEST_PROCESS' or
+ * 'REQUEST_PROCESS_REVERSE' EventFlags associated with the status message
+ * queue. The result of processing may be one of the following:
+ * OK if there were no errors during processing;
+ * INVALID_ARGUMENTS if audio buffers are invalid;
+ * INVALID_STATE if the engine has finished the disable phase;
+ * NOT_INITIALIZED if the audio buffers were not set;
+ * NOT_SUPPORTED if the requested processing type is not supported by
+ * the effect.
+ *
+ * @return retval OK if both message queues were created successfully.
+ * INVALID_STATE if the method was already called.
+ * INVALID_ARGUMENTS if there was a problem setting up
+ * the queue.
+ * @return statusMQ a message queue used for passing status from the effect.
+ */
+ @callflow(next={"setProcessBuffers"})
+ prepareForProcessing() generates (Result retval, fmq_sync<Result> statusMQ);
+
+ /**
+ * Set up input and output buffers for processing audio data. The effect
+ * may modify both the input and the output buffer during the operation.
+ * Buffers may be set multiple times during effect lifetime.
+ *
+ * The input and the output buffer may be reused between different effects,
+ * and the input buffer may be used as an output buffer. Buffers are
+ * distinguished using 'AudioBuffer.id' field.
+ *
+ * @param inBuffer input audio buffer.
+ * @param outBuffer output audio buffer.
+ * @return retval OK if both buffers were mapped successfully.
+ * INVALID_ARGUMENTS if there was a problem with mapping
+ * any of the buffers.
+ */
+ setProcessBuffers(AudioBuffer inBuffer, AudioBuffer outBuffer)
+ generates (Result retval);
+
+ /**
+ * Execute a vendor specific command on the effect. The command code
+ * and data, as well as result data are not interpreted by Android
+ * Framework and are passed as-is between the application and the effect.
+ *
+ * The effect must use standard POSIX.1-2001 error codes for the operation
+ * completion status.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param commandId the ID of the command.
+ * @param data command data.
+ * @param resultMaxSize maximum size in bytes of the result; can be 0.
+ * @return status command completion status.
+ * @return result result data.
+ */
+ command(uint32_t commandId, vec<uint8_t> data, uint32_t resultMaxSize)
+ generates (int32_t status, vec<uint8_t> result);
+
+ /**
+ * Set a vendor-specific parameter and apply it immediately. The parameter
+ * code and data are not interpreted by Android Framework and are passed
+ * as-is between the application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the parameter ID is
+ * unknown or if provided parameter data is invalid. If the effect does not
+ * support setting vendor-specific parameters, it must return NOT_SUPPORTED.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param parameter identifying data of the parameter.
+ * @param value the value of the parameter.
+ * @return retval operation completion status.
+ */
+ setParameter(vec<uint8_t> parameter, vec<uint8_t> value)
+ generates (Result retval);
+
+ /**
+ * Get a vendor-specific parameter value. The parameter code and returned
+ * data are not interpreted by Android Framework and are passed as-is
+ * between the application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the parameter ID is
+ * unknown. If the effect does not support setting vendor-specific
+ * parameters, it must return NOT_SUPPORTED.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param parameter identifying data of the parameter.
+ * @param valueMaxSize maximum size in bytes of the value.
+ * @return retval operation completion status.
+ * @return result the value of the parameter.
+ */
+ getParameter(vec<uint8_t> parameter, uint32_t valueMaxSize)
+ generates (Result retval, vec<uint8_t> value);
+
+ /**
+ * Get supported configs for a vendor-specific feature. The configs returned
+ * are not interpreted by Android Framework and are passed as-is between the
+ * application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+ * unknown. If the effect does not support getting vendor-specific feature
+ * configs, it must return NOT_SUPPORTED. If the feature is supported but
+ * the total number of supported configurations exceeds the maximum number
+ * indicated by the caller, the method must return RESULT_TOO_BIG.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param featureId feature identifier.
+ * @param maxConfigs maximum number of configs to return.
+ * @param configSize size of each config in bytes.
+ * @return retval operation completion status.
+ * @return configsCount number of configs returned.
+ * @return configsData data for all the configs returned.
+ */
+ getSupportedConfigsForFeature(
+ uint32_t featureId,
+ uint32_t maxConfigs,
+ uint32_t configSize) generates (
+ Result retval,
+ uint32_t configsCount,
+ vec<uint8_t> configsData);
+
+ /**
+ * Get the current config for a vendor-specific feature. The config returned
+ * is not interpreted by Android Framework and is passed as-is between the
+ * application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+ * unknown. If the effect does not support getting vendor-specific
+ * feature configs, it must return NOT_SUPPORTED.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param featureId feature identifier.
+ * @param configSize size of the config in bytes.
+ * @return retval operation completion status.
+ * @return configData config data.
+ */
+ getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize)
+ generates (Result retval, vec<uint8_t> configData);
+
+ /**
+ * Set the current config for a vendor-specific feature. The config data
+ * is not interpreted by Android Framework and is passed as-is between the
+ * application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+ * unknown. If the effect does not support getting vendor-specific
+ * feature configs, it must return NOT_SUPPORTED.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param featureId feature identifier.
+ * @param configData config data.
+ * @return retval operation completion status.
+ */
+ setCurrentConfigForFeature(uint32_t featureId, vec<uint8_t> configData)
+ generates (Result retval);
+
+ /**
+ * Called by the framework to deinitialize the effect and free up
+ * all the currently allocated resources. It is recommended to close
+ * the effect on the client side as soon as it is becomes unused.
+ *
+ * @return retval OK in case the success.
+ * INVALID_STATE if the effect was already closed.
+ */
+ @exit
+ close() generates (Result retval);
+};
diff --git a/audio/effect/4.0/IEffectBufferProviderCallback.hal b/audio/effect/4.0/IEffectBufferProviderCallback.hal
new file mode 100644
index 0000000..439383b
--- /dev/null
+++ b/audio/effect/4.0/IEffectBufferProviderCallback.hal
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+/**
+ * This callback interface contains functions that can be used by the effect
+ * engine 'process' function to exchange input and output audio buffers.
+ */
+interface IEffectBufferProviderCallback {
+ /**
+ * Called to retrieve a buffer where data should read from by 'process'
+ * function.
+ *
+ * @return buffer audio buffer for processing
+ */
+ getBuffer() generates (AudioBuffer buffer);
+
+ /**
+ * Called to provide a buffer with the data written by 'process' function.
+ *
+ * @param buffer audio buffer for processing
+ */
+ putBuffer(AudioBuffer buffer);
+};
diff --git a/audio/effect/4.0/IEffectsFactory.hal b/audio/effect/4.0/IEffectsFactory.hal
new file mode 100644
index 0000000..034af58
--- /dev/null
+++ b/audio/effect/4.0/IEffectsFactory.hal
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IEffectsFactory {
+ /**
+ * Returns descriptors of different effects in all loaded libraries.
+ *
+ * @return retval operation completion status.
+ * @return result list of effect descriptors.
+ */
+ getAllDescriptors() generates(Result retval, vec<EffectDescriptor> result);
+
+ /**
+ * Returns a descriptor of a particular effect.
+ *
+ * @return retval operation completion status.
+ * @return result effect descriptor.
+ */
+ getDescriptor(Uuid uid) generates(Result retval, EffectDescriptor result);
+
+ /**
+ * Creates an effect engine of the specified type. To release the effect
+ * engine, it is necessary to release references to the returned effect
+ * object.
+ *
+ * @param uid effect uuid.
+ * @param session audio session to which this effect instance will be
+ * attached. All effects created with the same session ID
+ * are connected in series and process the same signal
+ * stream.
+ * @param ioHandle identifies the output or input stream this effect is
+ * directed to in audio HAL.
+ * @return retval operation completion status.
+ * @return result the interface for the created effect.
+ * @return effectId the unique ID of the effect to be used with
+ * IStream::addEffect and IStream::removeEffect methods.
+ */
+ createEffect(Uuid uid, AudioSession session, AudioIoHandle ioHandle)
+ generates (Result retval, IEffect result, uint64_t effectId);
+};
diff --git a/audio/effect/4.0/IEnvironmentalReverbEffect.hal b/audio/effect/4.0/IEnvironmentalReverbEffect.hal
new file mode 100644
index 0000000..21264d2
--- /dev/null
+++ b/audio/effect/4.0/IEnvironmentalReverbEffect.hal
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IEnvironmentalReverbEffect extends IEffect {
+ /**
+ * Sets whether the effect should be bypassed.
+ */
+ setBypass(bool bypass) generates (Result retval);
+
+ /**
+ * Gets whether the effect should be bypassed.
+ */
+ getBypass() generates (Result retval, bool bypass);
+
+ enum ParamRange : int16_t {
+ ROOM_LEVEL_MIN = -6000,
+ ROOM_LEVEL_MAX = 0,
+ ROOM_HF_LEVEL_MIN = -4000,
+ ROOM_HF_LEVEL_MAX = 0,
+ DECAY_TIME_MIN = 100,
+ DECAY_TIME_MAX = 20000,
+ DECAY_HF_RATIO_MIN = 100,
+ DECAY_HF_RATIO_MAX = 1000,
+ REFLECTIONS_LEVEL_MIN = -6000,
+ REFLECTIONS_LEVEL_MAX = 0,
+ REFLECTIONS_DELAY_MIN = 0,
+ REFLECTIONS_DELAY_MAX = 65,
+ REVERB_LEVEL_MIN = -6000,
+ REVERB_LEVEL_MAX = 0,
+ REVERB_DELAY_MIN = 0,
+ REVERB_DELAY_MAX = 65,
+ DIFFUSION_MIN = 0,
+ DIFFUSION_MAX = 1000,
+ DENSITY_MIN = 0,
+ DENSITY_MAX = 1000
+ };
+
+ /**
+ * Sets the room level.
+ */
+ setRoomLevel(int16_t roomLevel) generates (Result retval);
+
+ /**
+ * Gets the room level.
+ */
+ getRoomLevel() generates (Result retval, int16_t roomLevel);
+
+ /**
+ * Sets the room high frequencies level.
+ */
+ setRoomHfLevel(int16_t roomHfLevel) generates (Result retval);
+
+ /**
+ * Gets the room high frequencies level.
+ */
+ getRoomHfLevel() generates (Result retval, int16_t roomHfLevel);
+
+ /**
+ * Sets the room decay time.
+ */
+ setDecayTime(uint32_t decayTime) generates (Result retval);
+
+ /**
+ * Gets the room decay time.
+ */
+ getDecayTime() generates (Result retval, uint32_t decayTime);
+
+ /**
+ * Sets the ratio of high frequencies decay.
+ */
+ setDecayHfRatio(int16_t decayHfRatio) generates (Result retval);
+
+ /**
+ * Gets the ratio of high frequencies decay.
+ */
+ getDecayHfRatio() generates (Result retval, int16_t decayHfRatio);
+
+ /**
+ * Sets the level of reflections in the room.
+ */
+ setReflectionsLevel(int16_t reflectionsLevel) generates (Result retval);
+
+ /**
+ * Gets the level of reflections in the room.
+ */
+ getReflectionsLevel() generates (Result retval, int16_t reflectionsLevel);
+
+ /**
+ * Sets the reflections delay in the room.
+ */
+ setReflectionsDelay(uint32_t reflectionsDelay) generates (Result retval);
+
+ /**
+ * Gets the reflections delay in the room.
+ */
+ getReflectionsDelay() generates (Result retval, uint32_t reflectionsDelay);
+
+ /**
+ * Sets the reverb level of the room.
+ */
+ setReverbLevel(int16_t reverbLevel) generates (Result retval);
+
+ /**
+ * Gets the reverb level of the room.
+ */
+ getReverbLevel() generates (Result retval, int16_t reverbLevel);
+
+ /**
+ * Sets the reverb delay of the room.
+ */
+ setReverbDelay(uint32_t reverDelay) generates (Result retval);
+
+ /**
+ * Gets the reverb delay of the room.
+ */
+ getReverbDelay() generates (Result retval, uint32_t reverbDelay);
+
+ /**
+ * Sets room diffusion.
+ */
+ setDiffusion(int16_t diffusion) generates (Result retval);
+
+ /**
+ * Gets room diffusion.
+ */
+ getDiffusion() generates (Result retval, int16_t diffusion);
+
+ /**
+ * Sets room wall density.
+ */
+ setDensity(int16_t density) generates (Result retval);
+
+ /**
+ * Gets room wall density.
+ */
+ getDensity() generates (Result retval, int16_t density);
+
+ struct AllProperties {
+ int16_t roomLevel; // in millibels, range -6000 to 0
+ int16_t roomHfLevel; // in millibels, range -4000 to 0
+ uint32_t decayTime; // in milliseconds, range 100 to 20000
+ int16_t decayHfRatio; // in permilles, range 100 to 1000
+ int16_t reflectionsLevel; // in millibels, range -6000 to 0
+ uint32_t reflectionsDelay; // in milliseconds, range 0 to 65
+ int16_t reverbLevel; // in millibels, range -6000 to 0
+ uint32_t reverbDelay; // in milliseconds, range 0 to 65
+ int16_t diffusion; // in permilles, range 0 to 1000
+ int16_t density; // in permilles, range 0 to 1000
+ };
+
+ /**
+ * Sets all properties at once.
+ */
+ setAllProperties(AllProperties properties) generates (Result retval);
+
+ /**
+ * Gets all properties at once.
+ */
+ getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/4.0/IEqualizerEffect.hal b/audio/effect/4.0/IEqualizerEffect.hal
new file mode 100644
index 0000000..58f2b73
--- /dev/null
+++ b/audio/effect/4.0/IEqualizerEffect.hal
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IEqualizerEffect extends IEffect {
+ /**
+ * Gets the number of frequency bands that the equalizer supports.
+ */
+ getNumBands() generates (Result retval, uint16_t numBands);
+
+ /**
+ * Returns the minimum and maximum band levels supported.
+ */
+ getLevelRange()
+ generates (Result retval, int16_t minLevel, int16_t maxLevel);
+
+ /**
+ * Sets the gain for the given equalizer band.
+ */
+ setBandLevel(uint16_t band, int16_t level) generates (Result retval);
+
+ /**
+ * Gets the gain for the given equalizer band.
+ */
+ getBandLevel(uint16_t band) generates (Result retval, int16_t level);
+
+ /**
+ * Gets the center frequency of the given band, in milliHertz.
+ */
+ getBandCenterFrequency(uint16_t band)
+ generates (Result retval, uint32_t centerFreqmHz);
+
+ /**
+ * Gets the frequency range of the given frequency band, in milliHertz.
+ */
+ getBandFrequencyRange(uint16_t band)
+ generates (Result retval, uint32_t minFreqmHz, uint32_t maxFreqmHz);
+
+ /**
+ * Gets the band that has the most effect on the given frequency
+ * in milliHertz.
+ */
+ getBandForFrequency(uint32_t freqmHz)
+ generates (Result retval, uint16_t band);
+
+ /**
+ * Gets the names of all presets the equalizer supports.
+ */
+ getPresetNames() generates (Result retval, vec<string> names);
+
+ /**
+ * Sets the current preset using the index of the preset in the names
+ * vector returned via 'getPresetNames'.
+ */
+ setCurrentPreset(uint16_t preset) generates (Result retval);
+
+ /**
+ * Gets the current preset.
+ */
+ getCurrentPreset() generates (Result retval, uint16_t preset);
+
+ struct AllProperties {
+ uint16_t curPreset;
+ vec<int16_t> bandLevels;
+ };
+
+ /**
+ * Sets all properties at once.
+ */
+ setAllProperties(AllProperties properties) generates (Result retval);
+
+ /**
+ * Gets all properties at once.
+ */
+ getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/4.0/ILoudnessEnhancerEffect.hal b/audio/effect/4.0/ILoudnessEnhancerEffect.hal
new file mode 100644
index 0000000..2421834
--- /dev/null
+++ b/audio/effect/4.0/ILoudnessEnhancerEffect.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface ILoudnessEnhancerEffect extends IEffect {
+ /**
+ * Sets target gain expressed in millibels.
+ */
+ setTargetGain(int32_t targetGainMb) generates (Result retval);
+
+ /**
+ * Gets target gain expressed in millibels.
+ */
+ getTargetGain() generates (Result retval, int32_t targetGainMb);
+};
diff --git a/audio/effect/4.0/INoiseSuppressionEffect.hal b/audio/effect/4.0/INoiseSuppressionEffect.hal
new file mode 100644
index 0000000..ce593a0
--- /dev/null
+++ b/audio/effect/4.0/INoiseSuppressionEffect.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface INoiseSuppressionEffect extends IEffect {
+ enum Level : int32_t {
+ LOW,
+ MEDIUM,
+ HIGH
+ };
+
+ /**
+ * Sets suppression level.
+ */
+ setSuppressionLevel(Level level) generates (Result retval);
+
+ /**
+ * Gets suppression level.
+ */
+ getSuppressionLevel() generates (Result retval, Level level);
+
+ enum Type : int32_t {
+ SINGLE_CHANNEL,
+ MULTI_CHANNEL
+ };
+
+ /**
+ * Set suppression type.
+ */
+ setSuppressionType(Type type) generates (Result retval);
+
+ /**
+ * Get suppression type.
+ */
+ getSuppressionType() generates (Result retval, Type type);
+
+ struct AllProperties {
+ Level level;
+ Type type;
+ };
+
+ /**
+ * Sets all properties at once.
+ */
+ setAllProperties(AllProperties properties) generates (Result retval);
+
+ /**
+ * Gets all properties at once.
+ */
+ getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/4.0/IPresetReverbEffect.hal b/audio/effect/4.0/IPresetReverbEffect.hal
new file mode 100644
index 0000000..2417235
--- /dev/null
+++ b/audio/effect/4.0/IPresetReverbEffect.hal
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IPresetReverbEffect extends IEffect {
+ enum Preset : int32_t {
+ NONE, // no reverb or reflections
+ SMALLROOM, // a small room less than five meters in length
+ MEDIUMROOM, // a medium room with a length of ten meters or less
+ LARGEROOM, // a large-sized room suitable for live performances
+ MEDIUMHALL, // a medium-sized hall
+ LARGEHALL, // a large-sized hall suitable for a full orchestra
+ PLATE, // synthesis of the traditional plate reverb
+ LAST = PLATE
+ };
+
+ /**
+ * Sets the current preset.
+ */
+ setPreset(Preset preset) generates (Result retval);
+
+ /**
+ * Gets the current preset.
+ */
+ getPreset() generates (Result retval, Preset preset);
+};
diff --git a/audio/effect/4.0/IVirtualizerEffect.hal b/audio/effect/4.0/IVirtualizerEffect.hal
new file mode 100644
index 0000000..52038ca
--- /dev/null
+++ b/audio/effect/4.0/IVirtualizerEffect.hal
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IVirtualizerEffect extends IEffect {
+ /**
+ * Returns whether setting virtualization strength is supported.
+ */
+ isStrengthSupported() generates (bool strengthSupported);
+
+ enum StrengthRange : uint16_t {
+ MIN = 0,
+ MAX = 1000
+ };
+
+ /**
+ * Sets virtualization strength.
+ *
+ * @param strength strength of the effect. The valid range for strength
+ * strength is [0, 1000], where 0 per mille designates the
+ * mildest effect and 1000 per mille designates the
+ * strongest.
+ * @return retval operation completion status.
+ */
+ setStrength(uint16_t strength) generates (Result retval);
+
+ /**
+ * Gets virtualization strength.
+ */
+ getStrength() generates (Result retval, uint16_t strength);
+
+ struct SpeakerAngle {
+ /** Speaker channel mask */
+ bitfield<AudioChannelMask> mask;
+ // all angles are expressed in degrees and
+ // are relative to the listener.
+ int16_t azimuth; // 0 is the direction the listener faces
+ // 180 is behind the listener
+ // -90 is to their left
+ int16_t elevation; // 0 is the horizontal plane
+ // +90 is above the listener, -90 is below
+ };
+ /**
+ * Retrieves virtual speaker angles for the given channel mask on the
+ * specified device.
+ */
+ getVirtualSpeakerAngles(bitfield<AudioChannelMask> mask, AudioDevice device)
+ generates (Result retval, vec<SpeakerAngle> speakerAngles);
+
+ /**
+ * Forces the virtualizer effect for the given output device.
+ */
+ forceVirtualizationMode(AudioDevice device) generates (Result retval);
+
+ /**
+ * Returns audio device reflecting the current virtualization mode,
+ * AUDIO_DEVICE_NONE when not virtualizing.
+ */
+ getVirtualizationMode() generates (Result retval, AudioDevice device);
+};
diff --git a/audio/effect/4.0/IVisualizerEffect.hal b/audio/effect/4.0/IVisualizerEffect.hal
new file mode 100644
index 0000000..2fee980
--- /dev/null
+++ b/audio/effect/4.0/IVisualizerEffect.hal
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IVisualizerEffect extends IEffect {
+ enum CaptureSizeRange : int32_t {
+ MAX = 1024, // maximum capture size in samples
+ MIN = 128 // minimum capture size in samples
+ };
+
+ /**
+ * Sets the number PCM samples in the capture.
+ */
+ setCaptureSize(uint16_t captureSize) generates (Result retval);
+
+ /**
+ * Gets the number PCM samples in the capture.
+ */
+ getCaptureSize() generates (Result retval, uint16_t captureSize);
+
+ enum ScalingMode : int32_t {
+ // Keep in sync with SCALING_MODE_... in
+ // frameworks/base/media/java/android/media/audiofx/Visualizer.java
+ NORMALIZED = 0,
+ AS_PLAYED = 1
+ };
+
+ /**
+ * Specifies the way the captured data is scaled.
+ */
+ setScalingMode(ScalingMode scalingMode) generates (Result retval);
+
+ /**
+ * Retrieves the way the captured data is scaled.
+ */
+ getScalingMode() generates (Result retval, ScalingMode scalingMode);
+
+ /**
+ * Informs the visualizer about the downstream latency.
+ */
+ setLatency(uint32_t latencyMs) generates (Result retval);
+
+ /**
+ * Gets the downstream latency.
+ */
+ getLatency() generates (Result retval, uint32_t latencyMs);
+
+ enum MeasurementMode : int32_t {
+ // Keep in sync with MEASUREMENT_MODE_... in
+ // frameworks/base/media/java/android/media/audiofx/Visualizer.java
+ NONE = 0x0,
+ PEAK_RMS = 0x1
+ };
+
+ /**
+ * Specifies which measurements are to be made.
+ */
+ setMeasurementMode(MeasurementMode measurementMode)
+ generates (Result retval);
+
+ /**
+ * Retrieves which measurements are to be made.
+ */
+ getMeasurementMode() generates (
+ Result retval, MeasurementMode measurementMode);
+
+ /**
+ * Retrieves the latest PCM snapshot captured by the visualizer engine. The
+ * number of samples to capture is specified by 'setCaptureSize' parameter.
+ *
+ * @return retval operation completion status.
+ * @return samples samples in 8 bit unsigned format (0 = 0x80)
+ */
+ capture() generates (Result retval, vec<uint8_t> samples);
+
+ struct Measurement {
+ MeasurementMode mode; // discriminator
+ union Values {
+ struct PeakAndRms {
+ int32_t peakMb; // millibels
+ int32_t rmsMb; // millibels
+ } peakAndRms;
+ } value;
+ };
+ /**
+ * Retrieves the latest measurements. The measurements to be made
+ * are specified by 'setMeasurementMode' parameter.
+ *
+ * @return retval operation completion status.
+ * @return result measurement.
+ */
+ measure() generates (Result retval, Measurement result);
+};
diff --git a/audio/effect/4.0/types.hal b/audio/effect/4.0/types.hal
new file mode 100644
index 0000000..0f76601
--- /dev/null
+++ b/audio/effect/4.0/types.hal
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+
+enum Result : int32_t {
+ OK,
+ NOT_INITIALIZED,
+ INVALID_ARGUMENTS,
+ INVALID_STATE,
+ NOT_SUPPORTED,
+ RESULT_TOO_BIG
+};
+
+/**
+ * Effect engine capabilities/requirements flags.
+ *
+ * Definitions for flags field of effect descriptor.
+ *
+ * +----------------+--------+--------------------------------------------------
+ * | description | bits | values
+ * +----------------+--------+--------------------------------------------------
+ * | connection | 0..2 | 0 insert: after track process
+ * | mode | | 1 auxiliary: connect to track auxiliary
+ * | | | output and use send level
+ * | | | 2 replace: replaces track process function;
+ * | | | must implement SRC, volume and mono to stereo.
+ * | | | 3 pre processing: applied below audio HAL on in
+ * | | | 4 post processing: applied below audio HAL on out
+ * | | | 5 - 7 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | insertion | 3..5 | 0 none
+ * | preference | | 1 first of the chain
+ * | | | 2 last of the chain
+ * | | | 3 exclusive (only effect in the insert chain)
+ * | | | 4..7 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Volume | 6..8 | 0 none
+ * | management | | 1 implements volume control
+ * | | | 2 requires volume indication
+ * | | | 4 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Device | 9..11 | 0 none
+ * | indication | | 1 requires device updates
+ * | | | 2, 4 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Sample input | 12..13 | 1 direct: process() function or
+ * | mode | | EFFECT_CMD_SET_CONFIG command must specify
+ * | | | a buffer descriptor
+ * | | | 2 provider: process() function uses the
+ * | | | bufferProvider indicated by the
+ * | | | EFFECT_CMD_SET_CONFIG command to request input.
+ * | | | buffers.
+ * | | | 3 both: both input modes are supported
+ * +----------------+--------+--------------------------------------------------
+ * | Sample output | 14..15 | 1 direct: process() function or
+ * | mode | | EFFECT_CMD_SET_CONFIG command must specify
+ * | | | a buffer descriptor
+ * | | | 2 provider: process() function uses the
+ * | | | bufferProvider indicated by the
+ * | | | EFFECT_CMD_SET_CONFIG command to request output
+ * | | | buffers.
+ * | | | 3 both: both output modes are supported
+ * +----------------+--------+--------------------------------------------------
+ * | Hardware | 16..17 | 0 No hardware acceleration
+ * | acceleration | | 1 non tunneled hw acceleration: the process()
+ * | | | function reads the samples, send them to HW
+ * | | | accelerated effect processor, reads back
+ * | | | the processed samples and returns them
+ * | | | to the output buffer.
+ * | | | 2 tunneled hw acceleration: the process()
+ * | | | function is transparent. The effect interface
+ * | | | is only used to control the effect engine.
+ * | | | This mode is relevant for global effects
+ * | | | actually applied by the audio hardware on
+ * | | | the output stream.
+ * +----------------+--------+--------------------------------------------------
+ * | Audio Mode | 18..19 | 0 none
+ * | indication | | 1 requires audio mode updates
+ * | | | 2..3 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Audio source | 20..21 | 0 none
+ * | indication | | 1 requires audio source updates
+ * | | | 2..3 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Effect offload | 22 | 0 The effect cannot be offloaded to an audio DSP
+ * | supported | | 1 The effect can be offloaded to an audio DSP
+ * +----------------+--------+--------------------------------------------------
+ * | Process | 23 | 0 The effect implements a process function.
+ * | function | | 1 The effect does not implement a process
+ * | not | | function: enabling the effect has no impact
+ * | implemented | | on latency or CPU load.
+ * | | | Effect implementations setting this flag do not
+ * | | | have to implement a process function.
+ * +----------------+--------+--------------------------------------------------
+ */
+@export(name="", value_prefix="EFFECT_FLAG_")
+enum EffectFlags : int32_t {
+ // Insert mode
+ TYPE_SHIFT = 0,
+ TYPE_SIZE = 3,
+ TYPE_MASK = ((1 << TYPE_SIZE) -1) << TYPE_SHIFT,
+ TYPE_INSERT = 0 << TYPE_SHIFT,
+ TYPE_AUXILIARY = 1 << TYPE_SHIFT,
+ TYPE_REPLACE = 2 << TYPE_SHIFT,
+ TYPE_PRE_PROC = 3 << TYPE_SHIFT,
+ TYPE_POST_PROC = 4 << TYPE_SHIFT,
+
+ // Insert preference
+ INSERT_SHIFT = TYPE_SHIFT + TYPE_SIZE,
+ INSERT_SIZE = 3,
+ INSERT_MASK = ((1 << INSERT_SIZE) -1) << INSERT_SHIFT,
+ INSERT_ANY = 0 << INSERT_SHIFT,
+ INSERT_FIRST = 1 << INSERT_SHIFT,
+ INSERT_LAST = 2 << INSERT_SHIFT,
+ INSERT_EXCLUSIVE = 3 << INSERT_SHIFT,
+
+ // Volume control
+ VOLUME_SHIFT = INSERT_SHIFT + INSERT_SIZE,
+ VOLUME_SIZE = 3,
+ VOLUME_MASK = ((1 << VOLUME_SIZE) -1) << VOLUME_SHIFT,
+ VOLUME_CTRL = 1 << VOLUME_SHIFT,
+ VOLUME_IND = 2 << VOLUME_SHIFT,
+ VOLUME_NONE = 0 << VOLUME_SHIFT,
+
+ // Device indication
+ DEVICE_SHIFT = VOLUME_SHIFT + VOLUME_SIZE,
+ DEVICE_SIZE = 3,
+ DEVICE_MASK = ((1 << DEVICE_SIZE) -1) << DEVICE_SHIFT,
+ DEVICE_IND = 1 << DEVICE_SHIFT,
+ DEVICE_NONE = 0 << DEVICE_SHIFT,
+
+ // Sample input modes
+ INPUT_SHIFT = DEVICE_SHIFT + DEVICE_SIZE,
+ INPUT_SIZE = 2,
+ INPUT_MASK = ((1 << INPUT_SIZE) -1) << INPUT_SHIFT,
+ INPUT_DIRECT = 1 << INPUT_SHIFT,
+ INPUT_PROVIDER = 2 << INPUT_SHIFT,
+ INPUT_BOTH = 3 << INPUT_SHIFT,
+
+ // Sample output modes
+ OUTPUT_SHIFT = INPUT_SHIFT + INPUT_SIZE,
+ OUTPUT_SIZE = 2,
+ OUTPUT_MASK = ((1 << OUTPUT_SIZE) -1) << OUTPUT_SHIFT,
+ OUTPUT_DIRECT = 1 << OUTPUT_SHIFT,
+ OUTPUT_PROVIDER = 2 << OUTPUT_SHIFT,
+ OUTPUT_BOTH = 3 << OUTPUT_SHIFT,
+
+ // Hardware acceleration mode
+ HW_ACC_SHIFT = OUTPUT_SHIFT + OUTPUT_SIZE,
+ HW_ACC_SIZE = 2,
+ HW_ACC_MASK = ((1 << HW_ACC_SIZE) -1) << HW_ACC_SHIFT,
+ HW_ACC_SIMPLE = 1 << HW_ACC_SHIFT,
+ HW_ACC_TUNNEL = 2 << HW_ACC_SHIFT,
+
+ // Audio mode indication
+ AUDIO_MODE_SHIFT = HW_ACC_SHIFT + HW_ACC_SIZE,
+ AUDIO_MODE_SIZE = 2,
+ AUDIO_MODE_MASK = ((1 << AUDIO_MODE_SIZE) -1) << AUDIO_MODE_SHIFT,
+ AUDIO_MODE_IND = 1 << AUDIO_MODE_SHIFT,
+ AUDIO_MODE_NONE = 0 << AUDIO_MODE_SHIFT,
+
+ // Audio source indication
+ AUDIO_SOURCE_SHIFT = AUDIO_MODE_SHIFT + AUDIO_MODE_SIZE,
+ AUDIO_SOURCE_SIZE = 2,
+ AUDIO_SOURCE_MASK = ((1 << AUDIO_SOURCE_SIZE) -1) << AUDIO_SOURCE_SHIFT,
+ AUDIO_SOURCE_IND = 1 << AUDIO_SOURCE_SHIFT,
+ AUDIO_SOURCE_NONE = 0 << AUDIO_SOURCE_SHIFT,
+
+ // Effect offload indication
+ OFFLOAD_SHIFT = AUDIO_SOURCE_SHIFT + AUDIO_SOURCE_SIZE,
+ OFFLOAD_SIZE = 1,
+ OFFLOAD_MASK = ((1 << OFFLOAD_SIZE) -1) << OFFLOAD_SHIFT,
+ OFFLOAD_SUPPORTED = 1 << OFFLOAD_SHIFT,
+
+ // Effect has no process indication
+ NO_PROCESS_SHIFT = OFFLOAD_SHIFT + OFFLOAD_SIZE,
+ NO_PROCESS_SIZE = 1,
+ NO_PROCESS_MASK = ((1 << NO_PROCESS_SIZE) -1) << NO_PROCESS_SHIFT,
+ NO_PROCESS = 1 << NO_PROCESS_SHIFT
+};
+
+/**
+ * The effect descriptor contains necessary information to facilitate the
+ * enumeration of the effect engines present in a library.
+ */
+struct EffectDescriptor {
+ Uuid type; // UUID of to the OpenSL ES interface implemented
+ // by this effect
+ Uuid uuid; // UUID for this particular implementation
+ EffectFlags flags; // effect engine capabilities/requirements flags
+ uint16_t cpuLoad; // CPU load indication expressed in 0.1 MIPS units
+ // as estimated on an ARM9E core (ARMv5TE) with 0 WS
+ uint16_t memoryUsage; // data memory usage expressed in KB and includes
+ // only dynamically allocated memory
+ uint8_t[64] name; // human readable effect name
+ uint8_t[64] implementor; // human readable effect implementor name
+};
+
+/**
+ * A buffer is a chunk of audio data for processing. Multi-channel audio is
+ * always interleaved. The channel order is from LSB to MSB with regard to the
+ * channel mask definition in audio.h, audio_channel_mask_t, e.g.:
+ * Stereo: L, R; 5.1: FL, FR, FC, LFE, BL, BR.
+ *
+ * The buffer size is expressed in frame count, a frame being composed of
+ * samples for all channels at a given time. Frame size for unspecified format
+ * (AUDIO_FORMAT_OTHER) is 8 bit by definition.
+ */
+struct AudioBuffer {
+ uint64_t id;
+ uint32_t frameCount;
+ memory data;
+};
+
+@export(name="effect_buffer_access_e", value_prefix="EFFECT_BUFFER_")
+enum EffectBufferAccess : int32_t {
+ ACCESS_WRITE,
+ ACCESS_READ,
+ ACCESS_ACCUMULATE
+};
+
+/**
+ * Determines what fields of EffectBufferConfig need to be considered.
+ */
+@export(name="", value_prefix="EFFECT_CONFIG_")
+enum EffectConfigParameters : int32_t {
+ BUFFER = 0x0001, // buffer field
+ SMP_RATE = 0x0002, // samplingRate
+ CHANNELS = 0x0004, // channels
+ FORMAT = 0x0008, // format
+ ACC_MODE = 0x0010, // accessMode
+ // Note that the 2.0 ALL have been moved to an helper function
+};
+
+/**
+ * The buffer config structure specifies the input or output audio format
+ * to be used by the effect engine.
+ */
+struct EffectBufferConfig {
+ AudioBuffer buffer;
+ uint32_t samplingRateHz;
+ bitfield<AudioChannelMask> channels;
+ AudioFormat format;
+ EffectBufferAccess accessMode;
+ bitfield<EffectConfigParameters> mask;
+};
+
+struct EffectConfig {
+ EffectBufferConfig inputCfg;
+ EffectBufferConfig outputCfg;
+};
+
+@export(name="effect_feature_e", value_prefix="EFFECT_FEATURE_")
+enum EffectFeature : int32_t {
+ AUX_CHANNELS, // supports auxiliary channels
+ // (e.g. dual mic noise suppressor)
+ CNT
+};
+
+struct EffectAuxChannelsConfig {
+ bitfield<AudioChannelMask> mainChannels; // channel mask for main channels
+ bitfield<AudioChannelMask> auxChannels; // channel mask for auxiliary channels
+};
+
+struct EffectOffloadParameter {
+ bool isOffload; // true if the playback thread the effect
+ // is attached to is offloaded
+ AudioIoHandle ioHandle; // io handle of the playback thread
+ // the effect is attached to
+};
+
+/**
+ * The message queue flags used to synchronize reads and writes from
+ * the status message queue used by effects.
+ */
+enum MessageQueueFlagBits : uint32_t {
+ DONE_PROCESSING = 1 << 0,
+ REQUEST_PROCESS = 1 << 1,
+ REQUEST_PROCESS_REVERSE = 1 << 2,
+ REQUEST_QUIT = 1 << 3,
+ REQUEST_PROCESS_ALL =
+ REQUEST_PROCESS | REQUEST_PROCESS_REVERSE | REQUEST_QUIT
+};
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
index a967049..9335a6c 100644
--- a/automotive/audiocontrol/1.0/Android.bp
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -9,13 +9,11 @@
srcs: [
"types.hal",
"IAudioControl.hal",
- "IAudioControlCallback.hal",
],
interfaces: [
"android.hidl.base@1.0",
],
types: [
- "AudioResult",
"ContextNumber",
],
gen_java: true,
diff --git a/automotive/audiocontrol/1.0/IAudioControl.hal b/automotive/audiocontrol/1.0/IAudioControl.hal
index fe9ea8e..c029499 100644
--- a/automotive/audiocontrol/1.0/IAudioControl.hal
+++ b/automotive/audiocontrol/1.0/IAudioControl.hal
@@ -16,8 +16,6 @@
package android.hardware.automotive.audiocontrol@1.0;
-import IAudioControlCallback;
-
/**
* Interacts with the car's audio subsystem to manage audio sources and volumes
@@ -25,15 +23,6 @@
interface IAudioControl {
/**
- * Registers the required callback object so that we can be notified when the state
- * of the car's audio system changes. This call must be made when the interface is
- * initialized.
- */
- setCallback(IAudioControlCallback notificationObject)
- generates (AudioResult result);
-
-
- /**
* Called at startup once per context to get the mapping from ContextNumber to
* busAddress. This lets the car tell the framework to which physical output stream
* each context should be routed.
diff --git a/automotive/audiocontrol/1.0/IAudioControlCallback.hal b/automotive/audiocontrol/1.0/IAudioControlCallback.hal
deleted file mode 100644
index f5c227e..0000000
--- a/automotive/audiocontrol/1.0/IAudioControlCallback.hal
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package android.hardware.automotive.audiocontrol@1.0;
-
-
-/**
- * Implemented on client (framework) side to receive asynchronous updates from the car.
- */
-interface IAudioControlCallback {
-
- /**
- * When the HAL makes this call, any apps currently playing must be asked to
- * temporarily suspend playback (via an AudioManager::AUDIOFOCUS_LOSS_TRANSIENT event).
- *
- * This is only a suggestion. Apps may be slow to react or even ignore this message
- * entirely. Enforcement, if necessary, must be done at the AudioHAL level as the
- * samples are delivered. In most instances, this is the way a car should ask for
- * quiet if it needs it for some important situation, such as warning alarms or chimes.
- */
- oneway suggestPausePlayers();
-
-
- /**
- * When the HAL makes this case, any apps currently playing must be asked to stop
- * playing (via an AudioManager::AUDIOFOCUS_LOSS event). Once stopped, the apps must
- * not resume their playback.
- *
- * It should be noted that not all apps or sound sources honor this request, but this
- * at least gives an app the chance to do the right thing.
- * Because it premanently stops media, this call is expected to be used only rarely.
- * Perhaps in the event of an E-call, where resuming music might be undesirable assuming
- * the driver is now dealing with whatever the emergency is?
- */
- oneway suggestStopPlayers();
-
-
- /**
- * Receives calls from the HAL when Android should resume normal operations. If the previous
- * action was a requestPausePlayers, then things that were paused must be told they may
- * resume.
- */
- oneway resumePlayers();
-};
diff --git a/automotive/audiocontrol/1.0/default/Android.bp b/automotive/audiocontrol/1.0/default/Android.bp
index 614c58b..0e074dd 100644
--- a/automotive/audiocontrol/1.0/default/Android.bp
+++ b/automotive/audiocontrol/1.0/default/Android.bp
@@ -19,7 +19,6 @@
relative_install_path: "hw",
srcs: [
"AudioControl.cpp",
- "AudioControlCallback.cpp",
"service.cpp"
],
init_rc: ["android.hardware.automotive.audiocontrol@1.0-service.rc"],
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.cpp b/automotive/audiocontrol/1.0/default/AudioControl.cpp
index 419225d..b40f2ae 100644
--- a/automotive/audiocontrol/1.0/default/AudioControl.cpp
+++ b/automotive/audiocontrol/1.0/default/AudioControl.cpp
@@ -36,15 +36,6 @@
};
-// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
-Return<AudioResult> AudioControl::setCallback(const sp<IAudioControlCallback>& notificationObject) {
- // Hang onto the provided callback object for future use
- callback = notificationObject;
-
- return AudioResult::OK;
-}
-
-
Return<int32_t> AudioControl::getBusForContext(uint32_t contextNumber) {
if (contextNumber > sContextNumberMax) {
ALOGE("Unexpected context number %d (max expected is %d)", contextNumber, sContextCount);
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.h b/automotive/audiocontrol/1.0/default/AudioControl.h
index 3383875..89e41f9 100644
--- a/automotive/audiocontrol/1.0/default/AudioControl.h
+++ b/automotive/audiocontrol/1.0/default/AudioControl.h
@@ -23,16 +23,12 @@
struct AudioControl : public IAudioControl {
public:
// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
- Return<AudioResult> setCallback(const sp<IAudioControlCallback>& notificationObject) override;
Return<int32_t> getBusForContext(uint32_t contextNumber) override;
Return<void> setBalanceTowardRight(float value) override;
Return<void> setFadeTowardFront(float value) override;
// Implementation details
AudioControl();
-
-private:
- sp<IAudioControlCallback> callback;
};
} // namespace implementation
diff --git a/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp b/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp
deleted file mode 100644
index ea79cad..0000000
--- a/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "AudioControlCallback.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace audiocontrol {
-namespace V1_0 {
-namespace implementation {
-
-// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
-Return<void> AudioControlCallback::suggestPausePlayers() {
- // TODO implement in framework (this is called by the HAL implementation when needed)
- return Void();
-}
-
-Return<void> AudioControlCallback::suggestStopPlayers() {
- // TODO implement in framework (this is called by the HAL implementation when needed)
- return Void();
-}
-
-Return<void> AudioControlCallback::resumePlayers() {
- // TODO implement in framework (this is called by the HAL implementation when needed)
- return Void();
-}
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace audiocontrol
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/audiocontrol/1.0/default/AudioControlCallback.h b/automotive/audiocontrol/1.0/default/AudioControlCallback.h
deleted file mode 100644
index 1054548..0000000
--- a/automotive/audiocontrol/1.0/default/AudioControlCallback.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
-#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
-
-#include <android/hardware/automotive/audiocontrol/1.0/IAudioControlCallback.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace audiocontrol {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-// TODO: Move this into packages/services/Car...
-struct AudioControlCallback : public IAudioControlCallback {
- // Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
- Return<void> suggestPausePlayers() override;
- Return<void> suggestStopPlayers() override;
- Return<void> resumePlayers() override;
-
- // Methods from ::android::hidl::base::V1_0::IBase follow.
-
-};
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace audiocontrol
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
diff --git a/automotive/audiocontrol/1.0/types.hal b/automotive/audiocontrol/1.0/types.hal
index 6301d3a..04d8d35 100644
--- a/automotive/audiocontrol/1.0/types.hal
+++ b/automotive/audiocontrol/1.0/types.hal
@@ -33,12 +33,3 @@
NOTIFICATION, /* Notifications */
SYSTEM_SOUND, /* User interaction sounds (button clicks, etc) */
};
-
-
-/** Error codes used in AudioControl HAL interface. */
-enum AudioResult : uint32_t {
- OK = 0,
- NOT_AVAILABLE,
- INVALID_ARGUMENT,
- UNDERLYING_SERVICE_ERROR,
-};
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index a0d20f3..bdc44ef 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -48,7 +48,6 @@
"VehicleHvacFanDirection",
"VehicleHwKeyInputAction",
"VehicleIgnitionState",
- "VehicleInstrumentClusterType",
"VehiclePropConfig",
"VehiclePropValue",
"VehicleProperty",
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 18e8c40..7938b73 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -358,6 +358,14 @@
{.config =
{
+ .prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.int32Values = {toInt(VehicleOilLevel::NORMAL)}}},
+
+ {.config =
+ {
.prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::CONTINUOUS,
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index f673d1a..3001213 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -253,6 +253,19 @@
| VehicleArea:GLOBAL),
/**
+ * Engine oil level
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleOilLevel
+ */
+ ENGINE_OIL_LEVEL = (
+ 0x0303
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:INT32
+ | VehicleArea:GLOBAL),
+
+ /**
* Temperature of engine oil
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
@@ -433,7 +446,7 @@
* Parking brake state.
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
- * @access VehiclePropertyAccess:READ
+ * @access VehiclePropertyAccess:READ_WRITE
*/
PARKING_BRAKE_ON = (
0x0402
@@ -442,6 +455,18 @@
| VehicleArea:GLOBAL),
/**
+ * Auto-apply parking brake.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ PARKING_BRAKE_AUTO_APPLY = (
+ 0x0403
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:BOOLEAN
+ | VehicleArea:GLOBAL),
+
+ /**
* Driving status policy.
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
@@ -825,12 +850,14 @@
/**
* Fan Positions Available
*
- * This is a bit mask of fan positions available for the zone. Each entry in
- * vehicle_hvac_fan_direction is selected by bit position. For instance, if
- * only the FAN_DIRECTION_FACE (0x1) and FAN_DIRECTION_DEFROST (0x4) are available,
- * then this value shall be set to 0x12.
- *
- * 0x12 = (1 << 1) | (1 << 4)
+ * This is a bit mask of fan positions available for the zone. Each available fan direction is
+ * denoted by a separate entry in the vector. A fan direction may have multiple bits from
+ * vehicle_hvac_fan_direction set. For instance, a typical car may have the following setting:
+ * - [0] = FAN_DIRECTION_FACE (0x1)
+ * - [1] = FAN_DIRECTION_FLOOR (0x2)
+ * - [2] = FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR (0x3)
+ * - [3] = FAN_DIRECTION_DEFROST (0x4)
+ * - [4] = FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST (0x6)
*
* @change_mode VehiclePropertyChangeMode:STATIC
* @access VehiclePropertyAccess:READ
@@ -838,7 +865,7 @@
HVAC_FAN_DIRECTION_AVAILABLE = (
0x0511
| VehiclePropertyGroup:SYSTEM
- | VehiclePropertyType:INT32
+ | VehiclePropertyType:INT32_VEC
| VehicleArea:ZONE),
/**
@@ -988,41 +1015,6 @@
| VehicleArea:GLOBAL),
/**
- * Property to define instrument cluster information.
- * For VehicleInstrumentClusterType:EXTERNAL_DISPLAY:
- * READ:
- * int32Values[0] : The current screen mode index. Screen mode is defined
- * as a configuration in car service and represents
- * which area of screen is renderable.
- * int32Values[1] : Android can render to instrument cluster (=1) or
- * not(=0). When this is 0, instrument cluster may be
- * rendering some information in the area allocated for
- * android and android side rendering is invisible.
- * WRITE from android:
- * int32Values[0] : Preferred mode for android side. Depending on the app
- * rendering to instrument cluster, preferred mode can
- * change. Instrument cluster still needs to send
- * event with new mode to trigger actual mode change.
- * int32Values[1] : The current app context relevant for instrument
- * cluster. Use the same flag with
- * VehicleAudioContextFlag but this context represents
- * active apps, not active audio. Instrument cluster
- * side may change mode depending on the currently
- * active contexts.
- * When system boots up, Android side will write {0, 0, 0, 0} when it is
- * ready to render to instrument cluster. Before this message, rendering
- * from android must not be visible in the cluster.
- * @change_mode VehiclePropertyChangeMode:ON_CHANGE
- * @access VehiclePropertyAccess:READ_WRITE
- * @configArray 0:VehicleInstrumentClusterType 1:hw type
- */
- INSTRUMENT_CLUSTER_INFO = (
- 0x0A20
- | VehiclePropertyGroup:SYSTEM
- | VehiclePropertyType:INT32_VEC
- | VehicleArea:GLOBAL),
-
- /**
* Current date and time, encoded as Unix time.
* This value denotes the number of seconds that have elapsed since
* 1/1/1970.
@@ -1891,9 +1883,18 @@
enum VehicleHvacFanDirection : int32_t {
FACE = 0x1,
FLOOR = 0x2,
- FACE_AND_FLOOR = 0x3,
DEFROST = 0x4,
- DEFROST_AND_FLOOR = 0x5,
+};
+
+enum VehicleOilLevel : int32_t {
+ /**
+ * Oil level values
+ */
+ CRITICALLY_LOW = 0,
+ LOW = 1,
+ NORMAL = 2,
+ HIGH = 3,
+ ERROR = 4,
};
/**
@@ -2067,25 +2068,6 @@
};
/**
- * Represents instrument cluster type available in system
- */
-enum VehicleInstrumentClusterType : int32_t {
- /** Android has no access to instument cluster */
- NONE = 0,
-
- /**
- * Instrument cluster can communicate through vehicle hal with additional
- * properties to exchange meta-data
- */
- HAL_INTERFACE = 1,
-
- /**
- * Instrument cluster is external display where android can render contents
- */
- EXTERNAL_DISPLAY = 2,
-};
-
-/**
* Units used for int or float type with no attached enum types.
*/
enum VehicleUnit : int32_t {
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index a46bcac..e8982e5 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -516,7 +516,7 @@
if (req.buffers[i].acquireFence >= 0) {
native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
handle->data[0] = req.buffers[i].acquireFence;
- result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+ result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
}
}
@@ -554,7 +554,7 @@
result.outputBuffers[i].status = BufferStatus::ERROR;
native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
handle->data[0] = req.buffers[i].acquireFence;
- result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+ result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
notifyError(req.frameNumber, req.buffers[i].streamId, ErrorCode::ERROR_BUFFER);
} else {
result.outputBuffers[i].status = BufferStatus::OK;
@@ -562,7 +562,7 @@
if (req.buffers[i].acquireFence > 0) {
native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
handle->data[0] = req.buffers[i].acquireFence;
- result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+ result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
}
}
}
@@ -1543,6 +1543,7 @@
halBuf.fenceTimeout = true;
} else {
::close(halBuf.acquireFence);
+ halBuf.acquireFence = -1;
}
}
diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal
index 5ab6b88..c8ebb17 100644
--- a/camera/device/3.4/types.hal
+++ b/camera/device/3.4/types.hal
@@ -31,7 +31,7 @@
* by the framework by its buffer resolution and format, and additionally by the
* HAL with the gralloc usage flags and the maximum in-flight buffer count.
*
- * This version extends the @3.2 Stream with the physicalCameraId field.
+ * This version extends the @3.2 Stream with the physicalCameraId and bufferSize field.
*/
struct Stream {
/**
@@ -60,6 +60,21 @@
* instance names returned by getCameraIdList().
*/
string physicalCameraId;
+
+ /**
+ * The size of a buffer from this Stream, in bytes.
+ *
+ * For non PixelFormat::BLOB formats, this entry must be 0 and HAL should use
+ * android.hardware.graphics.mapper lockYCbCr API to get buffer layout.
+ *
+ * For BLOB format with dataSpace Dataspace::DEPTH, this must be zero and and HAL must
+ * determine the buffer size based on ANDROID_DEPTH_MAX_DEPTH_SAMPLES.
+ *
+ * For BLOB format with dataSpace Dataspace::JFIF, this must be non-zero and represent the
+ * maximal size HAL can lock using android.hardware.graphics.mapper lock API.
+ *
+ */
+ uint32_t bufferSize;
};
/**
@@ -170,7 +185,9 @@
* PhysicalCameraSetting:
*
* Individual camera settings for logical camera backed by multiple physical devices.
- * Clients are allowed to pass separate settings for each physical device.
+ * Clients are allowed to pass separate settings for each physical device that has
+ * corresponding configured HalStream and the respective stream id is present in the
+ * output buffers of the capture request.
*/
struct PhysicalCameraSetting {
/**
@@ -182,8 +199,9 @@
/**
* Contains the physical device camera id. Any settings passed by client here
- * should be applied for this physical device. In case the physical id is invalid
- * Hal should fail the process request and return Status::ILLEGAL_ARGUMENT.
+ * should be applied for this physical device. In case the physical id is invalid or
+ * it is not present among the last configured streams, Hal should fail the process
+ * request and return Status::ILLEGAL_ARGUMENT.
*/
string physicalCameraId;
@@ -223,7 +241,12 @@
/**
* A vector containing individual camera settings for logical camera backed by multiple physical
- * devices. In case the vector is empty, Hal should use the settings field in 'v3_2'.
+ * devices. In case the vector is empty, Hal should use the settings field in 'v3_2'. The
+ * individual settings should only be honored for physical devices that have respective Hal
+ * stream. Physical devices that have a corresponding Hal stream but don't have attached
+ * settings here should use the settings field in 'v3_2'.
+ * If any of the physical settings in the array are applied on one or more devices, then the
+ * visual effect on any Hal streams attached to the logical camera is undefined.
*/
vec<PhysicalCameraSetting> physicalCameraSettings;
};
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 4652efd..1405ea9 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -20,6 +20,7 @@
#include <mutex>
#include <regex>
#include <unordered_map>
+#include <unordered_set>
#include <condition_variable>
#include <inttypes.h>
@@ -28,6 +29,7 @@
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <binder/MemoryHeapBase.h>
@@ -531,8 +533,10 @@
}
};
- struct DeviceCb : public ICameraDeviceCallback {
+ struct DeviceCb : public V3_4::ICameraDeviceCallback {
DeviceCb(CameraHidlTest *parent) : mParent(parent) {}
+ Return<void> processCaptureResult_3_4(
+ const hidl_vec<V3_4::CaptureResult>& results) override;
Return<void> processCaptureResult(const hidl_vec<CaptureResult>& results) override;
Return<void> notify(const hidl_vec<NotifyMsg>& msgs) override;
@@ -627,6 +631,15 @@
::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2,
::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4);
+ void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
+ sp<ICameraProvider> provider,
+ const AvailableStream *previewThreshold,
+ const std::unordered_set<std::string>& physicalIds,
+ sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
+ V3_2::Stream* previewStream /*out*/,
+ device::V3_4::HalStreamConfiguration *halStreamConfig /*out*/,
+ bool *supportsPartialResults /*out*/,
+ uint32_t *partialResultCount /*out*/);
void configurePreviewStream(const std::string &name, int32_t deviceVersion,
sp<ICameraProvider> provider,
const AvailableStream *previewThreshold,
@@ -641,7 +654,7 @@
static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
static Status isLogicalMultiCamera(camera_metadata_t *staticMeta);
static Status getPhysicalCameraIds(camera_metadata_t *staticMeta,
- std::vector<std::string> *physicalIds/*out*/);
+ std::unordered_set<std::string> *physicalIds/*out*/);
static Status pickConstrainedModeSize(camera_metadata_t *staticMeta,
AvailableStream &hfrStream);
static Status isZSLModeAvailable(camera_metadata_t *staticMeta);
@@ -844,6 +857,27 @@
return Void();
}
+Return<void> CameraHidlTest::DeviceCb::processCaptureResult_3_4(
+ const hidl_vec<V3_4::CaptureResult>& results) {
+
+ if (nullptr == mParent) {
+ return Void();
+ }
+
+ bool notify = false;
+ std::unique_lock<std::mutex> l(mParent->mLock);
+ for (size_t i = 0 ; i < results.size(); i++) {
+ notify = processCaptureResultLocked(results[i].v3_2);
+ }
+
+ l.unlock();
+ if (notify) {
+ mParent->mResultCondition.notify_one();
+ }
+
+ return Void();
+}
+
Return<void> CameraHidlTest::DeviceCb::processCaptureResult(
const hidl_vec<CaptureResult>& results) {
if (nullptr == mParent) {
@@ -3304,7 +3338,7 @@
TEST_F(CameraHidlTest, processMultiCaptureRequestPreview) {
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
- static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+ static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
uint64_t bufferId = 1;
uint32_t frameNumber = 1;
::android::hardware::hidl_vec<uint8_t> settings;
@@ -3327,7 +3361,7 @@
ASSERT_TRUE(ret.isOk());
continue;
}
- std::vector<std::string> physicalIds;
+ std::unordered_set<std::string> physicalIds;
rc = getPhysicalCameraIds(staticMeta, &physicalIds);
ASSERT_TRUE(Status::OK == rc);
ASSERT_TRUE(physicalIds.size() > 1);
@@ -3336,22 +3370,23 @@
ret = session->close();
ASSERT_TRUE(ret.isOk());
- V3_2::Stream previewStream;
- HalStreamConfiguration halStreamConfig;
+ // Leave only 2 physical devices in the id set.
+ auto it = physicalIds.begin(); it++; it++;
+ physicalIds.erase(it, physicalIds.end());
+
+ V3_4::HalStreamConfiguration halStreamConfig;
bool supportsPartialResults = false;
uint32_t partialResultCount = 0;
- configurePreviewStream(name, deviceVersion, mProvider, &previewThreshold, &session /*out*/,
- &previewStream /*out*/, &halStreamConfig /*out*/,
- &supportsPartialResults /*out*/,
- &partialResultCount /*out*/);
- sp<device::V3_3::ICameraDeviceSession> session3_3;
+ V3_2::Stream previewStream;
sp<device::V3_4::ICameraDeviceSession> session3_4;
- castSession(session, deviceVersion, &session3_3, &session3_4);
+ configurePreviewStreams3_4(name, deviceVersion, mProvider, &previewThreshold, physicalIds,
+ &session3_4, &previewStream, &halStreamConfig /*out*/,
+ &supportsPartialResults /*out*/, &partialResultCount /*out*/);
ASSERT_NE(session3_4, nullptr);
std::shared_ptr<ResultMetadataQueue> resultQueue;
auto resultQueueRet =
- session->getCaptureResultMetadataQueue(
+ session3_4->getCaptureResultMetadataQueue(
[&resultQueue](const auto& descriptor) {
resultQueue = std::make_shared<ResultMetadataQueue>(
descriptor);
@@ -3365,38 +3400,40 @@
});
ASSERT_TRUE(resultQueueRet.isOk());
- InFlightRequest inflightReq = {1, false, supportsPartialResults,
- partialResultCount, resultQueue};
+ InFlightRequest inflightReq = {static_cast<ssize_t> (physicalIds.size()), false,
+ supportsPartialResults, partialResultCount, resultQueue};
RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
- ret = session->constructDefaultRequestSettings(reqTemplate,
+ ret = session3_4->constructDefaultRequestSettings(reqTemplate,
[&](auto status, const auto& req) {
ASSERT_EQ(Status::OK, status);
settings = req;
});
ASSERT_TRUE(ret.isOk());
+ ASSERT_TRUE(settings.size() > 0);
- sp<GraphicBuffer> gb = new GraphicBuffer(
- previewStream.width, previewStream.height,
- static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
- android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
- halStreamConfig.streams[0].consumerUsage));
- ASSERT_NE(nullptr, gb.get());
+ std::vector<sp<GraphicBuffer>> graphicBuffers;
+ graphicBuffers.reserve(physicalIds.size());
::android::hardware::hidl_vec<StreamBuffer> outputBuffers;
- outputBuffers.resize(1);
- outputBuffers[0] = {halStreamConfig.streams[0].id,
- bufferId,
- hidl_handle(gb->getNativeBuffer()->handle),
- BufferStatus::OK,
- nullptr,
- nullptr};
-
- StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
- nullptr};
+ outputBuffers.resize(physicalIds.size());
hidl_vec<V3_4::PhysicalCameraSetting> camSettings;
- camSettings.resize(2);
- camSettings[0] = {0, hidl_string(physicalIds[0]), settings};
- camSettings[1] = {0, hidl_string(physicalIds[1]), settings};
+ camSettings.resize(physicalIds.size());
+ size_t k = 0;
+ for (const auto physicalIdIt : physicalIds) {
+ sp<GraphicBuffer> gb = new GraphicBuffer(previewStream.width, previewStream.height,
+ static_cast<int32_t>(halStreamConfig.streams[k].v3_3.v3_2.overrideFormat), 1,
+ android_convertGralloc1To0Usage(
+ halStreamConfig.streams[k].v3_3.v3_2.producerUsage,
+ halStreamConfig.streams[k].v3_3.v3_2.consumerUsage));
+ ASSERT_NE(nullptr, gb.get());
+ outputBuffers[k] = {halStreamConfig.streams[k].v3_3.v3_2.id, bufferId,
+ hidl_handle(gb->getNativeBuffer()->handle), BufferStatus::OK, nullptr, nullptr};
+ graphicBuffers.push_back(gb);
+ camSettings[k] = {0, hidl_string(physicalIdIt), settings};
+ k++;
+ }
+
+ StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
V3_4::CaptureRequest request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
emptyInputBuffer, outputBuffers}, camSettings};
@@ -3421,22 +3458,20 @@
{
std::unique_lock<std::mutex> l(mLock);
while (!inflightReq.errorCodeValid &&
- ((0 < inflightReq.numBuffersLeft) ||
- (!inflightReq.haveResultMetadata))) {
+ ((0 < inflightReq.numBuffersLeft) ||
+ (!inflightReq.haveResultMetadata))) {
auto timeout = std::chrono::system_clock::now() +
- std::chrono::seconds(kStreamBufferTimeoutSec);
+ std::chrono::seconds(kStreamBufferTimeoutSec);
ASSERT_NE(std::cv_status::timeout,
mResultCondition.wait_until(l, timeout));
}
ASSERT_FALSE(inflightReq.errorCodeValid);
ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
- ASSERT_EQ(halStreamConfig.streams[0].id,
- inflightReq.resultOutputBuffers[0].streamId);
}
// Empty physical camera settings should fail process requests
- camSettings[1] = {0, hidl_string(physicalIds[1]), emptySettings};
+ camSettings[1].settings = emptySettings;
frameNumber++;
request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
emptyInputBuffer, outputBuffers}, camSettings};
@@ -3449,7 +3484,8 @@
ASSERT_EQ(Status::ILLEGAL_ARGUMENT, stat);
// Invalid physical camera id should fail process requests
- camSettings[1] = {0, invalidPhysicalId, settings};
+ camSettings[1].physicalCameraId = invalidPhysicalId;
+ camSettings[1].settings = settings;
request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
emptyInputBuffer, outputBuffers}, camSettings};
returnStatus = session3_4->processCaptureRequest_3_4(
@@ -3460,7 +3496,7 @@
ASSERT_TRUE(returnStatus.isOk());
ASSERT_EQ(Status::ILLEGAL_ARGUMENT, stat);
- ret = session->close();
+ ret = session3_4->close();
ASSERT_TRUE(ret.isOk());
}
}
@@ -3838,7 +3874,7 @@
// Generate a list of physical camera ids backing a logical multi-camera.
Status CameraHidlTest::getPhysicalCameraIds(camera_metadata_t *staticMeta,
- std::vector<std::string> *physicalIds) {
+ std::unordered_set<std::string> *physicalIds) {
if ((nullptr == staticMeta) || (nullptr == physicalIds)) {
return Status::ILLEGAL_ARGUMENT;
}
@@ -3856,7 +3892,7 @@
if (ids[i] == '\0') {
if (start != i) {
std::string currentId(reinterpret_cast<const char *> (ids + start));
- physicalIds->push_back(currentId);
+ physicalIds->emplace(currentId);
}
start = i + 1;
}
@@ -4028,6 +4064,111 @@
*config3_2 = {streams3_2, configMode};
}
+// Configure multiple preview streams using different physical ids.
+void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
+ sp<ICameraProvider> provider,
+ const AvailableStream *previewThreshold,
+ const std::unordered_set<std::string>& physicalIds,
+ sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
+ V3_2::Stream *previewStream /*out*/,
+ device::V3_4::HalStreamConfiguration *halStreamConfig /*out*/,
+ bool *supportsPartialResults /*out*/,
+ uint32_t *partialResultCount /*out*/) {
+ ASSERT_NE(nullptr, session3_4);
+ ASSERT_NE(nullptr, halStreamConfig);
+ ASSERT_NE(nullptr, previewStream);
+ ASSERT_NE(nullptr, supportsPartialResults);
+ ASSERT_NE(nullptr, partialResultCount);
+ ASSERT_FALSE(physicalIds.empty());
+
+ std::vector<AvailableStream> outputPreviewStreams;
+ ::android::sp<ICameraDevice> device3_x;
+ ALOGI("configureStreams: Testing camera device %s", name.c_str());
+ Return<void> ret;
+ ret = provider->getCameraDeviceInterface_V3_x(
+ name,
+ [&](auto status, const auto& device) {
+ ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
+ (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(device, nullptr);
+ device3_x = device;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ sp<DeviceCb> cb = new DeviceCb(this);
+ sp<ICameraDeviceSession> session;
+ ret = device3_x->open(
+ cb,
+ [&session](auto status, const auto& newSession) {
+ ALOGI("device::open returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(newSession, nullptr);
+ session = newSession;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ sp<device::V3_3::ICameraDeviceSession> session3_3;
+ castSession(session, deviceVersion, &session3_3, session3_4);
+ ASSERT_NE(nullptr, session3_4);
+
+ camera_metadata_t *staticMeta;
+ ret = device3_x->getCameraCharacteristics([&] (Status s,
+ CameraMetadata metadata) {
+ ASSERT_EQ(Status::OK, s);
+ staticMeta = clone_camera_metadata(
+ reinterpret_cast<const camera_metadata_t*>(metadata.data()));
+ ASSERT_NE(nullptr, staticMeta);
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ camera_metadata_ro_entry entry;
+ auto status = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &entry);
+ if ((0 == status) && (entry.count > 0)) {
+ *partialResultCount = entry.data.i32[0];
+ *supportsPartialResults = (*partialResultCount > 1);
+ }
+
+ outputPreviewStreams.clear();
+ auto rc = getAvailableOutputStreams(staticMeta,
+ outputPreviewStreams, previewThreshold);
+ free_camera_metadata(staticMeta);
+ ASSERT_EQ(Status::OK, rc);
+ ASSERT_FALSE(outputPreviewStreams.empty());
+
+ ::android::hardware::hidl_vec<V3_4::Stream> streams3_4(physicalIds.size());
+ int32_t streamId = 0;
+ for (auto const& physicalId : physicalIds) {
+ V3_4::Stream stream3_4 = {{streamId, StreamType::OUTPUT,
+ static_cast<uint32_t> (outputPreviewStreams[0].width),
+ static_cast<uint32_t> (outputPreviewStreams[0].height),
+ static_cast<PixelFormat> (outputPreviewStreams[0].format),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0, StreamRotation::ROTATION_0},
+ physicalId.c_str(), /*bufferSize*/ 0};
+ streams3_4[streamId++] = stream3_4;
+ }
+
+ ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+ config3_4 = {streams3_4, StreamConfigurationMode::NORMAL_MODE, {}};
+ RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
+ ret = (*session3_4)->constructDefaultRequestSettings(reqTemplate,
+ [&config3_4](auto status, const auto& req) {
+ ASSERT_EQ(Status::OK, status);
+ config3_4.sessionParams = req;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ ret = (*session3_4)->configureStreams_3_4(config3_4,
+ [&] (Status s, device::V3_4::HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(physicalIds.size(), halConfig.streams.size());
+ *halStreamConfig = halConfig;
+ });
+ *previewStream = streams3_4[0].v3_2;
+ ASSERT_TRUE(ret.isOk());
+}
+
// Open a device session and configure a preview stream.
void CameraHidlTest::configurePreviewStream(const std::string &name, int32_t deviceVersion,
sp<ICameraProvider> provider,
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index c444dde..002ff31 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -256,6 +256,14 @@
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.secure_element</name>
+ <version>1.0</version>
+ <interface>
+ <name>ISecureElement</name>
+ <instance>eSE1</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.sensors</name>
<version>1.0</version>
<interface>
diff --git a/drm/1.1/ICryptoFactory.hal b/drm/1.1/ICryptoFactory.hal
index a1a7480..1f8caa5 100644
--- a/drm/1.1/ICryptoFactory.hal
+++ b/drm/1.1/ICryptoFactory.hal
@@ -23,11 +23,11 @@
* crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
* which are used by a codec to decrypt protected video content.
*
- * The 1.1 factory must always create 1.1 ICryptoPlugin interfaces, which are
+ * The 1.1 factory must always create 1.0 ICryptoPlugin interfaces, which are
* returned via the 1.0 createPlugin method.
*
- * To use 1.1 features the caller must cast the returned interface to a
- * 1.1 HAL, using V1_1::ICryptoPlugin::castFrom().
+ * The ICryptoFactory hal is required because all top-level interfaces
+ * have to be updated in a minor uprev.
*/
interface ICryptoFactory extends @1.0::ICryptoFactory {
};
diff --git a/drm/1.1/IDrmPlugin.hal b/drm/1.1/IDrmPlugin.hal
index c32d2b5..7dd397a 100644
--- a/drm/1.1/IDrmPlugin.hal
+++ b/drm/1.1/IDrmPlugin.hal
@@ -23,6 +23,8 @@
import @1.1::DrmMetricGroup;
import @1.1::HdcpLevel;
import @1.1::KeyRequestType;
+import @1.0::SecureStopId;
+import @1.1::SecureStopRelease;
import @1.1::SecurityLevel;
/**
@@ -176,4 +178,56 @@
* plugin.
*/
getMetrics() generates (Status status, vec<DrmMetricGroup> metric_groups);
+
+ /**
+ * Get the IDs of all secure stops on the device
+ *
+ * @return status the status of the call. The status must be OK or
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stop
+ * IDs cannot be returned.
+ * @return secureStopIds a list of the IDs
+ */
+ getSecureStopIds() generates
+ (Status status, vec<SecureStopId> secureStopIds);
+
+ /**
+ * Release secure stops given a release message from the key server
+ *
+ * @param ssRelease the secure stop release message identifying one or more
+ * secure stops to release. ssRelease is opaque, it is passed directly from
+ * a DRM license server through the app and media framework to the vendor
+ * HAL module. The format and content of ssRelease must be defined by the
+ * DRM scheme being implemented according to this HAL. The DRM scheme
+ * can be identified by its UUID which can be queried using
+ * IDrmFactory::isCryptoSchemeSupported.
+ *
+ * @return status the status of the call. The status must be OK or one of
+ * the following errors: BAD_VALUE if ssRelease is invalid or
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stop
+ * cannot be released.
+ */
+ releaseSecureStops(SecureStopRelease ssRelease) generates (Status status);
+
+ /**
+ * Remove a secure stop given its secure stop ID, without requiring
+ * a secure stop release response message from the key server.
+ *
+ * @param secureStopId the ID of the secure stop to release.
+ *
+ * @return status the status of the call. The status must be OK or one of
+ * the following errors: BAD_VALUE if the secureStopId is invalid or
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stop
+ * cannot be released.
+ */
+ removeSecureStop(SecureStopId secureStopId) generates (Status status);
+
+ /**
+ * Remove all secure stops on the device without requiring a secure
+ * stop release response message from the key server.
+ *
+ * @return status the status of the call. The status must be OK or
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure
+ * stops cannot be removed.
+ */
+ removeAllSecureStops() generates (Status status);
};
diff --git a/drm/1.1/types.hal b/drm/1.1/types.hal
index 94a6e66..015f1b7 100644
--- a/drm/1.1/types.hal
+++ b/drm/1.1/types.hal
@@ -210,3 +210,10 @@
HW_SECURE_ALL,
};
+/**
+ * Encapsulates a secure stop release opaque object
+ */
+struct SecureStopRelease {
+ vec<uint8_t> opaqueData;
+};
+
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..782f283
--- /dev/null
+++ b/drm/1.1/vts/functional/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_test {
+ name: "VtsHalDrmV1_1TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "drm_hal_clearkey_test.cpp"
+ ],
+ static_libs: [
+ "android.hardware.drm@1.0",
+ "android.hardware.drm@1.1",
+ "android.hardware.drm@1.0-helper",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "libhidlmemory",
+ "libnativehelper",
+ "libssl",
+ "libcrypto",
+ ],
+}
diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
new file mode 100644
index 0000000..62cc8b6
--- /dev/null
+++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2017 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 "drm_hal_clearkey_test@1.1"
+
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/types.h>
+#include <android/hardware/drm/1.1/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/ServiceManagement.h>
+#include <hidlmemory/mapping.h>
+#include <log/log.h>
+#include <memory>
+#include <openssl/aes.h>
+#include <random>
+
+#include "VtsHalHidlTargetTestBase.h"
+#include "VtsHalHidlTargetTestEnvBase.h"
+
+namespace drm = ::android::hardware::drm;
+using ::android::hardware::drm::V1_0::BufferType;
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::V1_0::KeyedVector;
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::Mode;
+using ::android::hardware::drm::V1_0::Pattern;
+using ::android::hardware::drm::V1_0::SecureStop;
+using ::android::hardware::drm::V1_0::SecureStopId;
+using ::android::hardware::drm::V1_0::SessionId;
+using ::android::hardware::drm::V1_0::SharedBuffer;
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::drm::V1_0::SubSample;
+
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+using ::android::hardware::drm::V1_1::HdcpLevel;
+using ::android::hardware::drm::V1_1::ICryptoFactory;
+using ::android::hardware::drm::V1_1::IDrmFactory;
+using ::android::hardware::drm::V1_1::IDrmPlugin;
+using ::android::hardware::drm::V1_1::SecurityLevel;
+using ::android::hardware::drm::V1_1::SecurityLevel;
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+using std::string;
+using std::unique_ptr;
+using std::random_device;
+using std::map;
+using std::mt19937;
+using std::vector;
+
+/**
+ * These clearkey tests use white box knowledge of the legacy clearkey
+ * plugin to verify that the HIDL HAL services and interfaces are working.
+ * It is not intended to verify any vendor's HAL implementation. If you
+ * are looking for vendor HAL tests, see drm_hal_vendor_test.cpp
+ */
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
+
+// To be used in mpd to specify drm scheme for players
+static const uint8_t kClearKeyUUID[16] = {
+ 0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+ 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
+
+// Test environment for drm
+class DrmHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static DrmHidlEnvironment* Instance() {
+ static DrmHidlEnvironment* instance = new DrmHidlEnvironment;
+ return instance;
+ }
+
+ virtual void HidlSetUp() override { ALOGI("SetUp DrmHidlEnvironment"); }
+
+ virtual void HidlTearDown() override { ALOGI("TearDown DrmHidlEnvironment"); }
+
+ private:
+ DrmHidlEnvironment() {}
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(DrmHidlEnvironment);
+};
+
+
+class DrmHalClearkeyTest : public ::testing::VtsHalHidlTargetTestBase {
+public:
+ virtual void SetUp() override {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+
+ ALOGD("DrmHalClearkeyTest: Running test %s.%s", test_info->test_case_name(),
+ test_info->name());
+
+ auto manager = android::hardware::defaultServiceManager();
+ ASSERT_NE(nullptr, manager.get());
+ manager->listByInterface(IDrmFactory::descriptor,
+ [&](const hidl_vec<hidl_string> ®istered) {
+ for (const auto &instance : registered) {
+ sp<IDrmFactory> drmFactory =
+ ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>(instance);
+ drmPlugin = createDrmPlugin(drmFactory);
+ if (drmPlugin != nullptr) {
+ break;
+ }
+ }
+ }
+ );
+
+ manager->listByInterface(ICryptoFactory::descriptor,
+ [&](const hidl_vec<hidl_string> ®istered) {
+ for (const auto &instance : registered) {
+ sp<ICryptoFactory> cryptoFactory =
+ ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>(instance);
+ cryptoPlugin = createCryptoPlugin(cryptoFactory);
+ if (cryptoPlugin != nullptr) {
+ break;
+ }
+ }
+ }
+ );
+
+ ASSERT_NE(nullptr, drmPlugin.get()) << "Can't find clearkey drm@1.1 plugin";
+ ASSERT_NE(nullptr, cryptoPlugin.get()) << "Can't find clearkey crypto@1.1 plugin";
+ }
+
+
+ virtual void TearDown() override {}
+
+ SessionId openSession();
+ void closeSession(const SessionId& sessionId);
+ hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
+ sp<IMemory> getDecryptMemory(size_t size, size_t index);
+
+ private:
+ sp<IDrmPlugin> createDrmPlugin(sp<IDrmFactory> drmFactory) {
+ if (drmFactory == nullptr) {
+ return nullptr;
+ }
+ sp<IDrmPlugin> plugin = nullptr;
+ auto res = drmFactory->createPlugin(
+ kClearKeyUUID, "",
+ [&](Status status, const sp<drm::V1_0::IDrmPlugin>& pluginV1_0) {
+ EXPECT_EQ(Status::OK, status);
+ plugin = IDrmPlugin::castFrom(pluginV1_0);
+ });
+
+ if (!res.isOk()) {
+ ALOGE("createDrmPlugin remote call failed");
+ }
+ return plugin;
+ }
+
+ sp<ICryptoPlugin> createCryptoPlugin(sp<ICryptoFactory> cryptoFactory) {
+ if (cryptoFactory == nullptr) {
+ return nullptr;
+ }
+ sp<ICryptoPlugin> plugin = nullptr;
+ hidl_vec<uint8_t> initVec;
+ auto res = cryptoFactory->createPlugin(
+ kClearKeyUUID, initVec,
+ [&](Status status, const sp<drm::V1_0::ICryptoPlugin>& pluginV1_0) {
+ EXPECT_EQ(Status::OK, status);
+ plugin = pluginV1_0;
+ });
+ if (!res.isOk()) {
+ ALOGE("createCryptoPlugin remote call failed");
+ }
+ return plugin;
+ }
+
+protected:
+ template <typename CT>
+ bool ValueEquals(DrmMetricGroup::ValueType type, const std::string& expected, const CT& actual) {
+ return type == DrmMetricGroup::ValueType::STRING_TYPE && expected == actual.stringValue;
+ }
+
+ template <typename CT>
+ bool ValueEquals(DrmMetricGroup::ValueType type, const int64_t expected, const CT& actual) {
+ return type == DrmMetricGroup::ValueType::INT64_TYPE && expected == actual.int64Value;
+ }
+
+ template <typename CT>
+ bool ValueEquals(DrmMetricGroup::ValueType type, const double expected, const CT& actual) {
+ return type == DrmMetricGroup::ValueType::DOUBLE_TYPE && expected == actual.doubleValue;
+ }
+
+ template <typename AT, typename VT>
+ bool ValidateMetricAttributeAndValue(const DrmMetricGroup::Metric& metric,
+ const std::string& attributeName, const AT& attributeValue,
+ const std::string& componentName, const VT& componentValue) {
+ bool validAttribute = false;
+ bool validComponent = false;
+ for (DrmMetricGroup::Attribute attribute : metric.attributes) {
+ if (attribute.name == attributeName &&
+ ValueEquals(attribute.type, attributeValue, attribute)) {
+ validAttribute = true;
+ }
+ }
+ for (DrmMetricGroup::Value value : metric.values) {
+ if (value.componentName == componentName &&
+ ValueEquals(value.type, componentValue, value)) {
+ validComponent = true;
+ }
+ }
+ return validAttribute && validComponent;
+ }
+
+ template <typename AT, typename VT>
+ bool ValidateMetricAttributeAndValue(const hidl_vec<DrmMetricGroup>& metricGroups,
+ const std::string& metricName,
+ const std::string& attributeName, const AT& attributeValue,
+ const std::string& componentName, const VT& componentValue) {
+ bool foundMetric = false;
+ for (const auto& group : metricGroups) {
+ for (const auto& metric : group.metrics) {
+ if (metric.name == metricName) {
+ foundMetric = foundMetric || ValidateMetricAttributeAndValue(
+ metric, attributeName, attributeValue,
+ componentName, componentValue);
+ }
+ }
+ }
+ return foundMetric;
+ }
+
+ sp<IDrmPlugin> drmPlugin;
+ sp<ICryptoPlugin> cryptoPlugin;
+};
+
+
+/**
+ * Helper method to open a session and verify that a non-empty
+ * session ID is returned
+ */
+SessionId DrmHalClearkeyTest::openSession() {
+ SessionId sessionId;
+
+ auto res = drmPlugin->openSession(
+ [&sessionId](Status status, const SessionId& id) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_NE(0u, id.size());
+ sessionId = id;
+ });
+ EXPECT_OK(res);
+ return sessionId;
+}
+
+/**
+ * Helper method to close a session
+ */
+void DrmHalClearkeyTest::closeSession(const SessionId& sessionId) {
+ EXPECT_TRUE(drmPlugin->closeSession(sessionId).isOk());
+}
+
+/**
+ * Test that the plugin returns valid connected and max HDCP levels
+ */
+TEST_F(DrmHalClearkeyTest, GetHdcpLevels) {
+ auto res = drmPlugin->getHdcpLevels(
+ [&](Status status, const HdcpLevel &connectedLevel,
+ const HdcpLevel &maxLevel) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_GE(connectedLevel, HdcpLevel::HDCP_NONE);
+ EXPECT_LE(maxLevel, HdcpLevel::HDCP_NO_OUTPUT);
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Test that the plugin returns valid open and max session counts
+ */
+TEST_F(DrmHalClearkeyTest, GetSessionCounts) {
+ auto res = drmPlugin->getNumberOfSessions(
+ [&](Status status, uint32_t currentSessions,
+ uint32_t maxSessions) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_GT(maxSessions, (uint32_t)0);
+ EXPECT_GE(currentSessions, (uint32_t)0);
+ EXPECT_LE(currentSessions, maxSessions);
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Test that the plugin returns a valid security level for
+ * a valid session
+ */
+TEST_F(DrmHalClearkeyTest, GetSecurityLevel) {
+ SessionId session = openSession();
+ auto res = drmPlugin->getSecurityLevel(session,
+ [&](Status status, SecurityLevel level) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_GE(level, SecurityLevel::SW_SECURE_CRYPTO);
+ EXPECT_LE(level, SecurityLevel::HW_SECURE_ALL);
+ });
+ EXPECT_OK(res);
+ closeSession(session);
+}
+
+/**
+ * Test that the plugin returns the documented error
+ * when requesting the security level for an invalid sessionId
+ */
+TEST_F(DrmHalClearkeyTest, GetSecurityLevelInvalidSessionId) {
+ SessionId session;
+ auto res = drmPlugin->getSecurityLevel(session,
+ [&](Status status, SecurityLevel /*level*/) {
+ EXPECT_EQ(Status::BAD_VALUE, status);
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Test that setting all valid security levels on a valid sessionId
+ * is supported
+ */
+TEST_F(DrmHalClearkeyTest, SetSecurityLevel) {
+ SessionId session = openSession();
+ for (uint32_t level = static_cast<uint32_t>(SecurityLevel::SW_SECURE_CRYPTO);
+ level <= static_cast<uint32_t>(SecurityLevel::HW_SECURE_ALL); level++) {
+ EXPECT_EQ(Status::OK, drmPlugin->setSecurityLevel(session, static_cast<SecurityLevel>(level)));
+
+ // check that the level got set
+ auto res = drmPlugin->getSecurityLevel(session,
+ [&](Status status, SecurityLevel readLevel) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(level, static_cast<uint32_t>(readLevel));
+ });
+ EXPECT_OK(res);
+ }
+ closeSession(session);
+}
+
+/**
+ * Test that setting an invalid security level on a valid
+ * sessionId is prohibited with the documented error code.
+ */
+TEST_F(DrmHalClearkeyTest, SetInvalidSecurityLevel) {
+ SessionId session = openSession();
+ SecurityLevel level = static_cast<SecurityLevel>(
+ static_cast<uint32_t>(SecurityLevel::HW_SECURE_ALL) + 1);
+ Status status = drmPlugin->setSecurityLevel(session, level);
+ EXPECT_EQ(Status::BAD_VALUE, status);
+ closeSession(session);
+}
+
+/**
+ * Test that attempting to set security level on an invalid
+ * (empty) sessionId is prohibited with the documented error
+ * code.
+ */
+TEST_F(DrmHalClearkeyTest, SetSecurityLevelInvalidSessionId) {
+ SessionId session;
+ SecurityLevel level = SecurityLevel::SW_SECURE_CRYPTO;
+ EXPECT_EQ(Status::BAD_VALUE, drmPlugin->setSecurityLevel(session, level));
+}
+
+/**
+ * Test metrics are set appropriately for open and close operations.
+ */
+TEST_F(DrmHalClearkeyTest, GetMetricsSuccess) {
+ SessionId sessionId = openSession();
+ // The first close should be successful.
+ closeSession(sessionId);
+ // The second close should fail (not opened).
+ EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, drmPlugin->closeSession(sessionId));
+
+ auto res = drmPlugin->getMetrics([this](Status status, hidl_vec<DrmMetricGroup> metricGroups) {
+ EXPECT_EQ(Status::OK, status);
+
+ // Verify the open_session metric.
+ EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "open_session", "status",
+ (int64_t)0, "count", (int64_t)1));
+ // Verify the close_session - success metric.
+ EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
+ (int64_t)0, "count", (int64_t)1));
+ // Verify the close_session - error metric.
+ EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
+ (int64_t)Status::ERROR_DRM_SESSION_NOT_OPENED,
+ "count", (int64_t)1));
+ });
+}
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ DrmHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGI("Test result = %d", status);
+ return status;
+}
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index b4bad2c..0b27922 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -443,5 +443,9 @@
EXPECT_GE(data.position.ageSeconds, 0);
}
+
+ EXPECT_GE(data.time.timeEstimate, 1514764800000); // Jan 01 2018 00:00:00
+ EXPECT_GT(data.time.timeUncertaintyNs, 0);
+ EXPECT_GT(data.time.frequencyUncertaintyNsPerSec, 0);
}
}
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index ed2ecbb..9980ae0 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -4,11 +4,8 @@
vendor: true,
relative_install_path: "hw",
srcs: ["passthrough.cpp"],
- static_libs: [
- "android.hardware.graphics.allocator@2.0-passthrough",
- ],
header_libs: [
- "android.hardware.graphics.allocator@2.0-hal",
+ "android.hardware.graphics.allocator@2.0-passthrough",
],
shared_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -20,6 +17,7 @@
"liblog",
"libutils",
],
+ cflags: ["-DLOG_TAG=\"AllocatorHal\""],
}
cc_binary {
diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
index 2f3022e..8ca8200 100644
--- a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
+++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
@@ -39,11 +39,11 @@
namespace detail {
-// AllocatorImpl implements IAllocator on top of AllocatorHal
-template <typename IALLOCATOR, typename ALLOCATOR_HAL>
-class AllocatorImpl : public IALLOCATOR {
+// AllocatorImpl implements V2_*::IAllocator on top of V2_*::hal::AllocatorHal
+template <typename Interface, typename Hal>
+class AllocatorImpl : public Interface {
public:
- bool init(std::unique_ptr<ALLOCATOR_HAL> hal) {
+ bool init(std::unique_ptr<Hal> hal) {
mHal = std::move(hal);
return true;
}
@@ -74,7 +74,7 @@
}
protected:
- std::unique_ptr<ALLOCATOR_HAL> mHal;
+ std::unique_ptr<Hal> mHal;
};
} // namespace detail
diff --git a/graphics/allocator/2.0/utils/passthrough/Android.bp b/graphics/allocator/2.0/utils/passthrough/Android.bp
index b956565..95b92cf 100644
--- a/graphics/allocator/2.0/utils/passthrough/Android.bp
+++ b/graphics/allocator/2.0/utils/passthrough/Android.bp
@@ -1,12 +1,7 @@
-cc_library_static {
+cc_library_headers {
name: "android.hardware.graphics.allocator@2.0-passthrough",
defaults: ["hidl_defaults"],
vendor: true,
- srcs: [
- "Gralloc0Hal.cpp",
- "Gralloc1Hal.cpp",
- "GrallocLoader.cpp",
- ],
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
@@ -19,11 +14,11 @@
],
header_libs: [
"android.hardware.graphics.allocator@2.0-hal",
- "libgrallocmapperincludes",
+ "android.hardware.graphics.mapper@2.0-passthrough_headers",
],
export_header_lib_headers: [
"android.hardware.graphics.allocator@2.0-hal",
+ "android.hardware.graphics.mapper@2.0-passthrough_headers",
],
export_include_dirs: ["include"],
- cflags: ["-DLOG_TAG=\"AllocatorHal\""],
}
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
deleted file mode 100644
index 8edb7dc..0000000
--- a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#include <allocator-passthrough/2.0/Gralloc0Hal.h>
-
-#include <string.h>
-
-#include <GrallocBufferDescriptor.h>
-#include <hardware/gralloc.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
-
-Gralloc0Hal::~Gralloc0Hal() {
- if (mDevice) {
- gralloc_close(mDevice);
- }
-}
-
-bool Gralloc0Hal::initWithModule(const hw_module_t* module) {
- int result = gralloc_open(module, &mDevice);
- if (result) {
- ALOGE("failed to open gralloc0 device: %s", strerror(-result));
- mDevice = nullptr;
- return false;
- }
-
- return true;
-}
-
-std::string Gralloc0Hal::dumpDebugInfo() {
- char buf[4096] = {};
- if (mDevice->dump) {
- mDevice->dump(mDevice, buf, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- }
-
- return buf;
-}
-
-Error Gralloc0Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
- uint32_t* outStride,
- std::vector<const native_handle_t*>* outBuffers) {
- mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
- if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
- return Error::BAD_DESCRIPTOR;
- }
-
- Error error = Error::NONE;
- uint32_t stride = 0;
- std::vector<const native_handle_t*> buffers;
- buffers.reserve(count);
-
- // allocate the buffers
- for (uint32_t i = 0; i < count; i++) {
- const native_handle_t* tmpBuffer;
- uint32_t tmpStride;
- error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
- if (error != Error::NONE) {
- break;
- }
-
- buffers.push_back(tmpBuffer);
-
- if (stride == 0) {
- stride = tmpStride;
- } else if (stride != tmpStride) {
- // non-uniform strides
- error = Error::UNSUPPORTED;
- break;
- }
- }
-
- if (error != Error::NONE) {
- freeBuffers(buffers);
- return error;
- }
-
- *outStride = stride;
- *outBuffers = std::move(buffers);
-
- return Error::NONE;
-}
-
-void Gralloc0Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
- for (auto buffer : buffers) {
- int result = mDevice->free(mDevice, buffer);
- if (result != 0) {
- ALOGE("failed to free buffer %p: %d", buffer, result);
- }
- }
-}
-
-Error Gralloc0Hal::allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
- const native_handle_t** outBuffer, uint32_t* outStride) {
- if (info.layerCount > 1 || (info.usage >> 32) != 0) {
- return Error::BAD_VALUE;
- }
-
- const native_handle_t* buffer = nullptr;
- int stride = 0;
- int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
- info.usage, &buffer, &stride);
- switch (result) {
- case 0:
- *outBuffer = buffer;
- *outStride = stride;
- return Error::NONE;
- case -EINVAL:
- return Error::BAD_VALUE;
- default:
- return Error::NO_RESOURCES;
- }
-}
-
-} // namespace passthrough
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
deleted file mode 100644
index e343ecd..0000000
--- a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#include <allocator-passthrough/2.0/Gralloc1Hal.h>
-
-#include <string.h>
-
-#include <GrallocBufferDescriptor.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
-
-Gralloc1Hal::~Gralloc1Hal() {
- if (mDevice) {
- gralloc1_close(mDevice);
- }
-}
-
-bool Gralloc1Hal::initWithModule(const hw_module_t* module) {
- int result = gralloc1_open(module, &mDevice);
- if (result) {
- ALOGE("failed to open gralloc1 device: %s", strerror(-result));
- mDevice = nullptr;
- return false;
- }
-
- initCapabilities();
- if (!initDispatch()) {
- gralloc1_close(mDevice);
- mDevice = nullptr;
- return false;
- }
-
- return true;
-}
-
-void Gralloc1Hal::initCapabilities() {
- uint32_t count = 0;
- mDevice->getCapabilities(mDevice, &count, nullptr);
-
- std::vector<int32_t> capabilities(count);
- mDevice->getCapabilities(mDevice, &count, capabilities.data());
- capabilities.resize(count);
-
- for (auto capability : capabilities) {
- if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
- mCapabilities.layeredBuffers = true;
- break;
- }
- }
-}
-
-gralloc1_function_pointer_t Gralloc1Hal::getDispatchFunction(
- gralloc1_function_descriptor_t desc) const {
- auto pfn = mDevice->getFunction(mDevice, desc);
- if (!pfn) {
- ALOGE("failed to get gralloc1 function %d", desc);
- return nullptr;
- }
- return pfn;
-}
-
-bool Gralloc1Hal::initDispatch() {
- if (!initDispatchFunction(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
- return false;
- }
-
- if (mCapabilities.layeredBuffers) {
- if (!initDispatchFunction(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
- return false;
- }
- }
-
- return true;
-}
-
-std::string Gralloc1Hal::dumpDebugInfo() {
- uint32_t len = 0;
- mDispatch.dump(mDevice, &len, nullptr);
-
- std::vector<char> buf(len + 1);
- mDispatch.dump(mDevice, &len, buf.data());
- buf.resize(len + 1);
- buf[len] = '\0';
-
- return buf.data();
-}
-
-Error Gralloc1Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
- uint32_t* outStride,
- std::vector<const native_handle_t*>* outBuffers) {
- mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
- if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
- return Error::BAD_DESCRIPTOR;
- }
-
- gralloc1_buffer_descriptor_t desc;
- Error error = createDescriptor(descriptorInfo, &desc);
- if (error != Error::NONE) {
- return error;
- }
-
- uint32_t stride = 0;
- std::vector<const native_handle_t*> buffers;
- buffers.reserve(count);
-
- // allocate the buffers
- for (uint32_t i = 0; i < count; i++) {
- const native_handle_t* tmpBuffer;
- uint32_t tmpStride;
- error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
- if (error != Error::NONE) {
- break;
- }
-
- buffers.push_back(tmpBuffer);
-
- if (stride == 0) {
- stride = tmpStride;
- } else if (stride != tmpStride) {
- // non-uniform strides
- error = Error::UNSUPPORTED;
- break;
- }
- }
-
- mDispatch.destroyDescriptor(mDevice, desc);
-
- if (error != Error::NONE) {
- freeBuffers(buffers);
- return error;
- }
-
- *outStride = stride;
- *outBuffers = std::move(buffers);
-
- return Error::NONE;
-}
-
-void Gralloc1Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
- for (auto buffer : buffers) {
- int32_t error = mDispatch.release(mDevice, buffer);
- if (error != GRALLOC1_ERROR_NONE) {
- ALOGE("failed to free buffer %p: %d", buffer, error);
- }
- }
-}
-
-Error Gralloc1Hal::toError(int32_t error) {
- switch (error) {
- case GRALLOC1_ERROR_NONE:
- return Error::NONE;
- case GRALLOC1_ERROR_BAD_DESCRIPTOR:
- return Error::BAD_DESCRIPTOR;
- case GRALLOC1_ERROR_BAD_HANDLE:
- return Error::BAD_BUFFER;
- case GRALLOC1_ERROR_BAD_VALUE:
- return Error::BAD_VALUE;
- case GRALLOC1_ERROR_NOT_SHARED:
- return Error::NONE; // this is fine
- case GRALLOC1_ERROR_NO_RESOURCES:
- return Error::NO_RESOURCES;
- case GRALLOC1_ERROR_UNDEFINED:
- case GRALLOC1_ERROR_UNSUPPORTED:
- default:
- return Error::UNSUPPORTED;
- }
-}
-
-uint64_t Gralloc1Hal::toProducerUsage(uint64_t usage) {
- // this is potentially broken as we have no idea which private flags
- // should be filtered out
- uint64_t producerUsage =
- usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
- BufferUsage::GPU_DATA_BUFFER);
-
- switch (usage & BufferUsage::CPU_WRITE_MASK) {
- case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
- producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
- break;
- case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
- producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
- break;
- default:
- break;
- }
-
- switch (usage & BufferUsage::CPU_READ_MASK) {
- case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
- producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
- break;
- case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
- producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
- break;
- default:
- break;
- }
-
- // BufferUsage::GPU_DATA_BUFFER is always filtered out
-
- return producerUsage;
-}
-
-uint64_t Gralloc1Hal::toConsumerUsage(uint64_t usage) {
- // this is potentially broken as we have no idea which private flags
- // should be filtered out
- uint64_t consumerUsage =
- usage &
- ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
- BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
-
- switch (usage & BufferUsage::CPU_READ_MASK) {
- case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
- consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
- break;
- case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
- consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
- break;
- default:
- break;
- }
-
- // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
-
- if (usage & BufferUsage::GPU_DATA_BUFFER) {
- consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
- }
-
- return consumerUsage;
-}
-
-Error Gralloc1Hal::createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
- gralloc1_buffer_descriptor_t* outDescriptor) {
- gralloc1_buffer_descriptor_t descriptor;
-
- int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
-
- if (error == GRALLOC1_ERROR_NONE) {
- error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
- }
- if (error == GRALLOC1_ERROR_NONE) {
- error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
- }
- if (error == GRALLOC1_ERROR_NONE) {
- if (mCapabilities.layeredBuffers) {
- error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
- } else if (info.layerCount > 1) {
- error = GRALLOC1_ERROR_UNSUPPORTED;
- }
- }
- if (error == GRALLOC1_ERROR_NONE) {
- error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
- }
- if (error == GRALLOC1_ERROR_NONE) {
- error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
- }
-
- if (error == GRALLOC1_ERROR_NONE) {
- *outDescriptor = descriptor;
- } else {
- mDispatch.destroyDescriptor(mDevice, descriptor);
- }
-
- return toError(error);
-}
-
-Error Gralloc1Hal::allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
- const native_handle_t** outBuffer, uint32_t* outStride) {
- const native_handle_t* buffer = nullptr;
- int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
- if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
- return toError(error);
- }
-
- uint32_t stride = 0;
- error = mDispatch.getStride(mDevice, buffer, &stride);
- if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
- mDispatch.release(mDevice, buffer);
- return toError(error);
- }
-
- *outBuffer = buffer;
- *outStride = stride;
-
- return Error::NONE;
-}
-
-} // namespace passthrough
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
deleted file mode 100644
index dae7a78..0000000
--- a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2017 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.
- */
-
-#include <allocator-passthrough/2.0/GrallocLoader.h>
-
-#include <allocator-hal/2.0/Allocator.h>
-#include <allocator-hal/2.0/AllocatorHal.h>
-#include <allocator-passthrough/2.0/Gralloc0Hal.h>
-#include <allocator-passthrough/2.0/Gralloc1Hal.h>
-#include <hardware/gralloc.h>
-#include <hardware/hardware.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-const hw_module_t* GrallocLoader::loadModule() {
- const hw_module_t* module;
- int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
- if (error) {
- ALOGE("failed to get gralloc module");
- return nullptr;
- }
-
- return module;
-}
-
-int GrallocLoader::getModuleMajorApiVersion(const hw_module_t* module) {
- return (module->module_api_version >> 8) & 0xff;
-}
-
-std::unique_ptr<hal::AllocatorHal> GrallocLoader::createHal(const hw_module_t* module) {
- int major = getModuleMajorApiVersion(module);
- switch (major) {
- case 1: {
- auto hal = std::make_unique<Gralloc1Hal>();
- return hal->initWithModule(module) ? std::move(hal) : nullptr;
- }
- case 0: {
- auto hal = std::make_unique<Gralloc0Hal>();
- return hal->initWithModule(module) ? std::move(hal) : nullptr;
- }
- default:
- ALOGE("unknown gralloc module major version %d", major);
- return nullptr;
- }
-}
-
-IAllocator* GrallocLoader::createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
- auto allocator = std::make_unique<hal::Allocator>();
- return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
-}
-
-} // namespace passthrough
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
index 8f433b0..6c179be 100644
--- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
@@ -16,10 +16,16 @@
#pragma once
-#include <allocator-hal/2.0/AllocatorHal.h>
+#ifndef LOG_TAG
+#warning "Gralloc0Hal.h included without LOG_TAG"
+#endif
-struct alloc_device_t;
-struct hw_module_t;
+#include <cstring> // for strerror
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
namespace android {
namespace hardware {
@@ -28,28 +34,125 @@
namespace V2_0 {
namespace passthrough {
+namespace detail {
+
using mapper::V2_0::BufferDescriptor;
using mapper::V2_0::Error;
+using mapper::V2_0::passthrough::grallocDecodeBufferDescriptor;
-class Gralloc0Hal : public virtual hal::AllocatorHal {
+// Gralloc0HalImpl implements V2_*::hal::AllocatorHal on top of gralloc0
+template <typename Hal>
+class Gralloc0HalImpl : public Hal {
public:
- ~Gralloc0Hal();
- bool initWithModule(const hw_module_t* module);
+ ~Gralloc0HalImpl() {
+ if (mDevice) {
+ gralloc_close(mDevice);
+ }
+ }
- std::string dumpDebugInfo() override;
+ bool initWithModule(const hw_module_t* module) {
+ int result = gralloc_open(module, &mDevice);
+ if (result) {
+ ALOGE("failed to open gralloc0 device: %s", strerror(-result));
+ mDevice = nullptr;
+ return false;
+ }
+
+ return true;
+ }
+
+ std::string dumpDebugInfo() override {
+ char buf[4096] = {};
+ if (mDevice->dump) {
+ mDevice->dump(mDevice, buf, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ }
+
+ return buf;
+ }
Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
- std::vector<const native_handle_t*>* outBuffers) override;
+ std::vector<const native_handle_t*>* outBuffers) override {
+ mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+ if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+ return Error::BAD_DESCRIPTOR;
+ }
- void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+ Error error = Error::NONE;
+ uint32_t stride = 0;
+ std::vector<const native_handle_t*> buffers;
+ buffers.reserve(count);
+
+ // allocate the buffers
+ for (uint32_t i = 0; i < count; i++) {
+ const native_handle_t* tmpBuffer;
+ uint32_t tmpStride;
+ error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
+ if (error != Error::NONE) {
+ break;
+ }
+
+ buffers.push_back(tmpBuffer);
+
+ if (stride == 0) {
+ stride = tmpStride;
+ } else if (stride != tmpStride) {
+ // non-uniform strides
+ error = Error::UNSUPPORTED;
+ break;
+ }
+ }
+
+ if (error != Error::NONE) {
+ freeBuffers(buffers);
+ return error;
+ }
+
+ *outStride = stride;
+ *outBuffers = std::move(buffers);
+
+ return Error::NONE;
+ }
+
+ void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
+ for (auto buffer : buffers) {
+ int result = mDevice->free(mDevice, buffer);
+ if (result != 0) {
+ ALOGE("failed to free buffer %p: %d", buffer, result);
+ }
+ }
+ }
protected:
Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
- const native_handle_t** outBuffer, uint32_t* outStride);
+ const native_handle_t** outBuffer, uint32_t* outStride) {
+ if (info.layerCount > 1 || (info.usage >> 32) != 0) {
+ return Error::BAD_VALUE;
+ }
+
+ const native_handle_t* buffer = nullptr;
+ int stride = 0;
+ int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
+ info.usage, &buffer, &stride);
+ switch (result) {
+ case 0:
+ *outBuffer = buffer;
+ *outStride = stride;
+ return Error::NONE;
+ case -EINVAL:
+ return Error::BAD_VALUE;
+ default:
+ return Error::NO_RESOURCES;
+ }
+ }
alloc_device_t* mDevice = nullptr;
};
+} // namespace detail
+
+using Gralloc0Hal = detail::Gralloc0HalImpl<hal::AllocatorHal>;
+
} // namespace passthrough
} // namespace V2_0
} // namespace allocator
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
index 3126e91..53b5c14 100644
--- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
@@ -16,8 +16,16 @@
#pragma once
+#ifndef LOG_TAG
+#warning "Gralloc1Hal.h included without LOG_TAG"
+#endif
+
+#include <cstring> // for strerror
+
#include <allocator-hal/2.0/AllocatorHal.h>
#include <hardware/gralloc1.h>
+#include <log/log.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
namespace android {
namespace hardware {
@@ -26,46 +34,302 @@
namespace V2_0 {
namespace passthrough {
+namespace detail {
+
+using common::V1_0::BufferUsage;
using mapper::V2_0::BufferDescriptor;
using mapper::V2_0::Error;
+using mapper::V2_0::passthrough::grallocDecodeBufferDescriptor;
-class Gralloc1Hal : public virtual hal::AllocatorHal {
+// Gralloc1HalImpl implements V2_*::hal::AllocatorHal on top of gralloc1
+template <typename Hal>
+class Gralloc1HalImpl : public Hal {
public:
- ~Gralloc1Hal();
- bool initWithModule(const hw_module_t* module);
+ ~Gralloc1HalImpl() {
+ if (mDevice) {
+ gralloc1_close(mDevice);
+ }
+ }
- std::string dumpDebugInfo() override;
+ bool initWithModule(const hw_module_t* module) {
+ int result = gralloc1_open(module, &mDevice);
+ if (result) {
+ ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+ mDevice = nullptr;
+ return false;
+ }
+
+ initCapabilities();
+ if (!initDispatch()) {
+ gralloc1_close(mDevice);
+ mDevice = nullptr;
+ return false;
+ }
+
+ return true;
+ }
+
+ std::string dumpDebugInfo() override {
+ uint32_t len = 0;
+ mDispatch.dump(mDevice, &len, nullptr);
+
+ std::vector<char> buf(len + 1);
+ mDispatch.dump(mDevice, &len, buf.data());
+ buf.resize(len + 1);
+ buf[len] = '\0';
+
+ return buf.data();
+ }
Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
- std::vector<const native_handle_t*>* outBuffers) override;
+ std::vector<const native_handle_t*>* outBuffers) override {
+ mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+ if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+ return Error::BAD_DESCRIPTOR;
+ }
- void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+ gralloc1_buffer_descriptor_t desc;
+ Error error = createDescriptor(descriptorInfo, &desc);
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ uint32_t stride = 0;
+ std::vector<const native_handle_t*> buffers;
+ buffers.reserve(count);
+
+ // allocate the buffers
+ for (uint32_t i = 0; i < count; i++) {
+ const native_handle_t* tmpBuffer;
+ uint32_t tmpStride;
+ error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
+ if (error != Error::NONE) {
+ break;
+ }
+
+ buffers.push_back(tmpBuffer);
+
+ if (stride == 0) {
+ stride = tmpStride;
+ } else if (stride != tmpStride) {
+ // non-uniform strides
+ error = Error::UNSUPPORTED;
+ break;
+ }
+ }
+
+ mDispatch.destroyDescriptor(mDevice, desc);
+
+ if (error != Error::NONE) {
+ freeBuffers(buffers);
+ return error;
+ }
+
+ *outStride = stride;
+ *outBuffers = std::move(buffers);
+
+ return Error::NONE;
+ }
+
+ void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
+ for (auto buffer : buffers) {
+ int32_t error = mDispatch.release(mDevice, buffer);
+ if (error != GRALLOC1_ERROR_NONE) {
+ ALOGE("failed to free buffer %p: %d", buffer, error);
+ }
+ }
+ }
protected:
+ virtual void initCapabilities() {
+ uint32_t count = 0;
+ mDevice->getCapabilities(mDevice, &count, nullptr);
+
+ std::vector<int32_t> capabilities(count);
+ mDevice->getCapabilities(mDevice, &count, capabilities.data());
+ capabilities.resize(count);
+
+ for (auto capability : capabilities) {
+ if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
+ mCapabilities.layeredBuffers = true;
+ break;
+ }
+ }
+ }
+
template <typename T>
- bool initDispatchFunction(gralloc1_function_descriptor_t desc, T* outPfn) {
- auto pfn = getDispatchFunction(desc);
+ bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
+ auto pfn = mDevice->getFunction(mDevice, desc);
if (pfn) {
*outPfn = reinterpret_cast<T>(pfn);
return true;
} else {
+ ALOGE("failed to get gralloc1 function %d", desc);
return false;
}
}
- gralloc1_function_pointer_t getDispatchFunction(gralloc1_function_descriptor_t desc) const;
- virtual void initCapabilities();
- virtual bool initDispatch();
+ virtual bool initDispatch() {
+ if (!initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
+ !initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
+ !initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
+ !initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
+ !initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
+ !initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
+ !initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
+ !initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
+ !initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
+ !initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
+ return false;
+ }
- static Error toError(int32_t error);
- static uint64_t toProducerUsage(uint64_t usage);
- static uint64_t toConsumerUsage(uint64_t usage);
+ if (mCapabilities.layeredBuffers) {
+ if (!initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static Error toError(int32_t error) {
+ switch (error) {
+ case GRALLOC1_ERROR_NONE:
+ return Error::NONE;
+ case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+ return Error::BAD_DESCRIPTOR;
+ case GRALLOC1_ERROR_BAD_HANDLE:
+ return Error::BAD_BUFFER;
+ case GRALLOC1_ERROR_BAD_VALUE:
+ return Error::BAD_VALUE;
+ case GRALLOC1_ERROR_NOT_SHARED:
+ return Error::NONE; // this is fine
+ case GRALLOC1_ERROR_NO_RESOURCES:
+ return Error::NO_RESOURCES;
+ case GRALLOC1_ERROR_UNDEFINED:
+ case GRALLOC1_ERROR_UNSUPPORTED:
+ default:
+ return Error::UNSUPPORTED;
+ }
+ }
+
+ static uint64_t toProducerUsage(uint64_t usage) {
+ // this is potentially broken as we have no idea which private flags
+ // should be filtered out
+ uint64_t producerUsage = usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
+ BufferUsage::CPU_WRITE_MASK |
+ BufferUsage::GPU_DATA_BUFFER);
+
+ switch (usage & BufferUsage::CPU_WRITE_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ switch (usage & BufferUsage::CPU_READ_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ // BufferUsage::GPU_DATA_BUFFER is always filtered out
+
+ return producerUsage;
+ }
+
+ static uint64_t toConsumerUsage(uint64_t usage) {
+ // this is potentially broken as we have no idea which private flags
+ // should be filtered out
+ uint64_t consumerUsage =
+ usage &
+ ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+ BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
+
+ switch (usage & BufferUsage::CPU_READ_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+ consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+ consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
+
+ if (usage & BufferUsage::GPU_DATA_BUFFER) {
+ consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
+ }
+
+ return consumerUsage;
+ }
Error createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
- gralloc1_buffer_descriptor_t* outDescriptor);
+ gralloc1_buffer_descriptor_t* outDescriptor) {
+ gralloc1_buffer_descriptor_t descriptor;
+
+ int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
+
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ if (mCapabilities.layeredBuffers) {
+ error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
+ } else if (info.layerCount > 1) {
+ error = GRALLOC1_ERROR_UNSUPPORTED;
+ }
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
+ }
+
+ if (error == GRALLOC1_ERROR_NONE) {
+ *outDescriptor = descriptor;
+ } else {
+ mDispatch.destroyDescriptor(mDevice, descriptor);
+ }
+
+ return toError(error);
+ }
Error allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
- const native_handle_t** outBuffer, uint32_t* outStride);
+ const native_handle_t** outBuffer, uint32_t* outStride) {
+ const native_handle_t* buffer = nullptr;
+ int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
+ if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
+ return toError(error);
+ }
+
+ uint32_t stride = 0;
+ error = mDispatch.getStride(mDevice, buffer, &stride);
+ if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
+ mDispatch.release(mDevice, buffer);
+ return toError(error);
+ }
+
+ *outBuffer = buffer;
+ *outStride = stride;
+
+ return Error::NONE;
+ }
gralloc1_device_t* mDevice = nullptr;
@@ -88,6 +352,10 @@
} mDispatch = {};
};
+} // namespace detail
+
+using Gralloc1Hal = detail::Gralloc1HalImpl<hal::AllocatorHal>;
+
} // namespace passthrough
} // namespace V2_0
} // namespace allocator
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
index a0b9503..660099b 100644
--- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
@@ -16,11 +16,18 @@
#pragma once
+#ifndef LOG_TAG
+#warning "GrallocLoader.h included without LOG_TAG"
+#endif
+
#include <memory>
-#include <allocator-hal/2.0/AllocatorHal.h>
-
-struct hw_module_t;
+#include <allocator-hal/2.0/Allocator.h>
+#include <allocator-passthrough/2.0/Gralloc0Hal.h>
+#include <allocator-passthrough/2.0/Gralloc1Hal.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -44,16 +51,45 @@
}
// load the gralloc module
- static const hw_module_t* loadModule();
+ static const hw_module_t* loadModule() {
+ const hw_module_t* module;
+ int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (error) {
+ ALOGE("failed to get gralloc module");
+ return nullptr;
+ }
+
+ return module;
+ }
// return the major api version of the module
- static int getModuleMajorApiVersion(const hw_module_t* module);
+ static int getModuleMajorApiVersion(const hw_module_t* module) {
+ return (module->module_api_version >> 8) & 0xff;
+ }
// create an AllocatorHal instance
- static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module);
+ static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module) {
+ int major = getModuleMajorApiVersion(module);
+ switch (major) {
+ case 1: {
+ auto hal = std::make_unique<Gralloc1Hal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+ case 0: {
+ auto hal = std::make_unique<Gralloc0Hal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+ default:
+ ALOGE("unknown gralloc module major version %d", major);
+ return nullptr;
+ }
+ }
// create an IAllocator instance
- static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal);
+ static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
+ auto allocator = std::make_unique<hal::Allocator>();
+ return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
+ }
};
} // namespace passthrough
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 40f18c0..92b65a3 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -58,8 +58,8 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.0-vts",
"libVtsHalGraphicsComposerTestUtils",
- "libVtsHalGraphicsMapperTestUtils",
"libnativehelper",
],
header_libs: [
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 9a749d7..376ee37 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -17,10 +17,10 @@
#define LOG_TAG "graphics_composer_hidl_hal_test"
#include <android-base/logging.h>
+#include <mapper-vts/2.0/MapperVts.h>
#include "GraphicsComposerCallback.h"
#include "TestCommandReader.h"
#include "VtsHalGraphicsComposerTestUtils.h"
-#include "VtsHalGraphicsMapperTestUtils.h"
#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
@@ -48,7 +48,7 @@
using android::hardware::graphics::common::V1_0::PixelFormat;
using android::hardware::graphics::common::V1_0::Transform;
using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
+using android::hardware::graphics::mapper::V2_0::vts::Gralloc;
using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
// Test environment for graphics.composer
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 0325a6c..78322a1 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -61,10 +61,10 @@
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@2.1",
"libVtsHalGraphicsComposerTestUtils",
"libVtsHalGraphicsComposerTestUtils@2.2",
- "libVtsHalGraphicsMapperTestUtils",
"libnativehelper",
],
header_libs: [
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 8b44d61..6fbdd3c 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -18,12 +18,12 @@
#include <android-base/logging.h>
#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-vts/2.0/MapperVts.h>
#include <sync/sync.h>
#include "2.2/VtsHalGraphicsComposerTestUtils.h"
#include "GraphicsComposerCallback.h"
#include "TestCommandReader.h"
#include "VtsHalGraphicsComposerTestUtils.h"
-#include "VtsHalGraphicsMapperTestUtils.h"
#include <VtsHalHidlTargetTestBase.h>
@@ -43,7 +43,7 @@
using android::hardware::graphics::common::V1_0::Transform;
using android::hardware::graphics::composer::V2_2::IComposerClient;
using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
+using android::hardware::graphics::mapper::V2_0::vts::Gralloc;
using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
// Test environment for graphics.composer
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
index 677d966..8874799 100644
--- a/graphics/mapper/2.0/default/Android.bp
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -18,8 +18,10 @@
defaults: ["hidl_defaults"],
vendor: true,
relative_install_path: "hw",
- srcs: ["GrallocMapper.cpp", "Gralloc0Mapper.cpp", "Gralloc1Mapper.cpp"],
- cppflags: ["-Wall", "-Wextra"],
+ srcs: ["passthrough.cpp"],
+ header_libs: [
+ "android.hardware.graphics.mapper@2.0-passthrough"
+ ],
shared_libs: [
"android.hardware.graphics.mapper@2.0",
"libbase",
@@ -31,10 +33,5 @@
"libsync",
"libutils",
],
-}
-
-cc_library_headers {
- name: "libgrallocmapperincludes",
- vendor: true,
- export_include_dirs: ["."],
+ cflags: ["-DLOG_TAG=\"MapperHal\""],
}
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
deleted file mode 100644
index 28f5016..0000000
--- a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2016 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 "Gralloc0Mapper"
-
-#include "Gralloc0Mapper.h"
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module)
- : mModule(reinterpret_cast<const gralloc_module_t*>(module)),
- mMinor(module->module_api_version & 0xff) {
- mCapabilities.highUsageBits = false;
- mCapabilities.layeredBuffers = false;
- mCapabilities.unregisterImplyDelete = false;
-}
-
-Error Gralloc0Mapper::registerBuffer(buffer_handle_t bufferHandle) {
- int result = mModule->registerBuffer(mModule, bufferHandle);
- return result ? Error::BAD_BUFFER : Error::NONE;
-}
-
-void Gralloc0Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
- mModule->unregisterBuffer(mModule, bufferHandle);
-}
-
-Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
- uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- void** outData) {
- int result;
- void* data = nullptr;
- if (mMinor >= 3 && mModule->lockAsync) {
- // Dup fenceFd as it is going to be owned by gralloc. Note that it is
- // gralloc's responsibility to close it, even on locking errors.
- if (fenceFd >= 0) {
- fenceFd = dup(fenceFd);
- if (fenceFd < 0) {
- return Error::NO_RESOURCES;
- }
- }
-
- result = mModule->lockAsync(mModule, bufferHandle, cpuUsage,
- accessRegion.left, accessRegion.top,
- accessRegion.width, accessRegion.height,
- &data, fenceFd);
- } else {
- waitFenceFd(fenceFd, "Gralloc0Mapper::lock");
-
- result = mModule->lock(mModule, bufferHandle, cpuUsage,
- accessRegion.left, accessRegion.top,
- accessRegion.width, accessRegion.height, &data);
- }
-
- if (result) {
- return Error::BAD_VALUE;
- } else {
- *outData = data;
- return Error::NONE;
- }
-}
-
-Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
- uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- YCbCrLayout* outLayout) {
- int result;
- android_ycbcr ycbcr = {};
- if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
- // Dup fenceFd as it is going to be owned by gralloc. Note that it is
- // gralloc's responsibility to close it, even on locking errors.
- if (fenceFd >= 0) {
- fenceFd = dup(fenceFd);
- if (fenceFd < 0) {
- return Error::NO_RESOURCES;
- }
- }
-
- result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage,
- accessRegion.left, accessRegion.top,
- accessRegion.width,
- accessRegion.height, &ycbcr, fenceFd);
- } else {
- waitFenceFd(fenceFd, "Gralloc0Mapper::lockYCbCr");
-
- if (mModule->lock_ycbcr) {
- result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage,
- accessRegion.left, accessRegion.top,
- accessRegion.width,
- accessRegion.height, &ycbcr);
- } else {
- result = -EINVAL;
- }
- }
-
- if (result) {
- return Error::BAD_VALUE;
- } else {
- outLayout->y = ycbcr.y;
- outLayout->cb = ycbcr.cb;
- outLayout->cr = ycbcr.cr;
- outLayout->yStride = ycbcr.ystride;
- outLayout->cStride = ycbcr.cstride;
- outLayout->chromaStep = ycbcr.chroma_step;
- return Error::NONE;
- }
-}
-
-Error Gralloc0Mapper::unlockBuffer(buffer_handle_t bufferHandle,
- int* outFenceFd) {
- int result;
- int fenceFd = -1;
- if (mMinor >= 3 && mModule->unlockAsync) {
- result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
- } else {
- result = mModule->unlock(mModule, bufferHandle);
- }
-
- if (result) {
- // we always own the fenceFd even when unlock failed
- if (fenceFd >= 0) {
- close(fenceFd);
- }
-
- return Error::BAD_VALUE;
- } else {
- *outFenceFd = fenceFd;
- return Error::NONE;
- }
-}
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace mapper
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.h b/graphics/mapper/2.0/default/Gralloc0Mapper.h
deleted file mode 100644
index e792a69..0000000
--- a/graphics/mapper/2.0/default/Gralloc0Mapper.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
-#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
-
-#include "GrallocMapper.h"
-
-#include <hardware/gralloc.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-class Gralloc0Mapper : public GrallocMapper {
- public:
- Gralloc0Mapper(const hw_module_t* module);
-
- private:
- Error registerBuffer(buffer_handle_t bufferHandle) override;
- void unregisterBuffer(buffer_handle_t bufferHandle) override;
- Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- void** outData) override;
- Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- YCbCrLayout* outLayout) override;
- Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
-
- const gralloc_module_t* mModule;
- uint8_t mMinor;
-};
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace mapper
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
deleted file mode 100644
index c1e5adc..0000000
--- a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright 2016 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 "Gralloc1Mapper"
-
-#include "Gralloc1Mapper.h"
-
-#include <vector>
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-
-Gralloc1Mapper::Gralloc1Mapper(const hw_module_t* module)
- : mDevice(nullptr), mDispatch() {
- int result = gralloc1_open(module, &mDevice);
- if (result) {
- LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
- strerror(-result));
- }
-
- initCapabilities();
- initDispatch();
-}
-
-Gralloc1Mapper::~Gralloc1Mapper() {
- gralloc1_close(mDevice);
-}
-
-void Gralloc1Mapper::initCapabilities() {
- mCapabilities.highUsageBits = true;
- mCapabilities.layeredBuffers = false;
- mCapabilities.unregisterImplyDelete = false;
-
- uint32_t count = 0;
- mDevice->getCapabilities(mDevice, &count, nullptr);
-
- std::vector<int32_t> capabilities(count);
- mDevice->getCapabilities(mDevice, &count, capabilities.data());
- capabilities.resize(count);
-
- for (auto capability : capabilities) {
- switch (capability) {
- case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
- mCapabilities.layeredBuffers = true;
- break;
- case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
- mCapabilities.unregisterImplyDelete = true;
- break;
- }
- }
-}
-
-template <typename T>
-void Gralloc1Mapper::initDispatch(gralloc1_function_descriptor_t desc,
- T* outPfn) {
- auto pfn = mDevice->getFunction(mDevice, desc);
- if (!pfn) {
- LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
- }
-
- *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void Gralloc1Mapper::initDispatch() {
- initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
- initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
- initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
- &mDispatch.getNumFlexPlanes);
- initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
- initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
- initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
-}
-
-Error Gralloc1Mapper::toError(int32_t error) {
- switch (error) {
- case GRALLOC1_ERROR_NONE:
- return Error::NONE;
- case GRALLOC1_ERROR_BAD_DESCRIPTOR:
- return Error::BAD_DESCRIPTOR;
- case GRALLOC1_ERROR_BAD_HANDLE:
- return Error::BAD_BUFFER;
- case GRALLOC1_ERROR_BAD_VALUE:
- return Error::BAD_VALUE;
- case GRALLOC1_ERROR_NOT_SHARED:
- return Error::NONE; // this is fine
- case GRALLOC1_ERROR_NO_RESOURCES:
- return Error::NO_RESOURCES;
- case GRALLOC1_ERROR_UNDEFINED:
- case GRALLOC1_ERROR_UNSUPPORTED:
- default:
- return Error::UNSUPPORTED;
- }
-}
-
-bool Gralloc1Mapper::toYCbCrLayout(const android_flex_layout& flex,
- YCbCrLayout* outLayout) {
- // must be YCbCr
- if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
- return false;
- }
-
- for (int i = 0; i < 3; i++) {
- const auto& plane = flex.planes[i];
- // must have 8-bit depth
- if (plane.bits_per_component != 8 || plane.bits_used != 8) {
- return false;
- }
-
- if (plane.component == FLEX_COMPONENT_Y) {
- // Y must not be interleaved
- if (plane.h_increment != 1) {
- return false;
- }
- } else {
- // Cb and Cr can be interleaved
- if (plane.h_increment != 1 && plane.h_increment != 2) {
- return false;
- }
- }
-
- if (!plane.v_increment) {
- return false;
- }
- }
-
- if (flex.planes[0].component != FLEX_COMPONENT_Y ||
- flex.planes[1].component != FLEX_COMPONENT_Cb ||
- flex.planes[2].component != FLEX_COMPONENT_Cr) {
- return false;
- }
-
- const auto& y = flex.planes[0];
- const auto& cb = flex.planes[1];
- const auto& cr = flex.planes[2];
-
- if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
- return false;
- }
-
- outLayout->y = y.top_left;
- outLayout->cb = cb.top_left;
- outLayout->cr = cr.top_left;
- outLayout->yStride = y.v_increment;
- outLayout->cStride = cb.v_increment;
- outLayout->chromaStep = cb.h_increment;
-
- return true;
-}
-
-gralloc1_rect_t Gralloc1Mapper::asGralloc1Rect(const IMapper::Rect& rect) {
- return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
-}
-
-Error Gralloc1Mapper::registerBuffer(buffer_handle_t bufferHandle) {
- return toError(mDispatch.retain(mDevice, bufferHandle));
-}
-
-void Gralloc1Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
- mDispatch.release(mDevice, bufferHandle);
-}
-
-Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
- uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- void** outData) {
- // Dup fenceFd as it is going to be owned by gralloc. Note that it is
- // gralloc's responsibility to close it, even on locking errors.
- if (fenceFd >= 0) {
- fenceFd = dup(fenceFd);
- if (fenceFd < 0) {
- return Error::NO_RESOURCES;
- }
- }
-
- const uint64_t consumerUsage =
- cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
- const auto accessRect = asGralloc1Rect(accessRegion);
- void* data = nullptr;
- int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage,
- consumerUsage, &accessRect, &data, fenceFd);
-
- if (error == GRALLOC1_ERROR_NONE) {
- *outData = data;
- }
-
- return toError(error);
-}
-
-Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
- uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- YCbCrLayout* outLayout) {
- // prepare flex layout
- android_flex_layout flex = {};
- int32_t error =
- mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
- if (error != GRALLOC1_ERROR_NONE) {
- return toError(error);
- }
- std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
- flex.planes = flexPlanes.data();
-
- // Dup fenceFd as it is going to be owned by gralloc. Note that it is
- // gralloc's responsibility to close it, even on locking errors.
- if (fenceFd >= 0) {
- fenceFd = dup(fenceFd);
- if (fenceFd < 0) {
- return Error::NO_RESOURCES;
- }
- }
-
- const uint64_t consumerUsage =
- cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
- const auto accessRect = asGralloc1Rect(accessRegion);
- error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage,
- &accessRect, &flex, fenceFd);
- if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
- ALOGD("unable to convert android_flex_layout to YCbCrLayout");
-
- // undo the lock
- fenceFd = -1;
- mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
- if (fenceFd >= 0) {
- close(fenceFd);
- }
-
- error = GRALLOC1_ERROR_BAD_HANDLE;
- }
-
- return toError(error);
-}
-
-Error Gralloc1Mapper::unlockBuffer(buffer_handle_t bufferHandle,
- int* outFenceFd) {
- int fenceFd = -1;
- int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
-
- if (error == GRALLOC1_ERROR_NONE) {
- *outFenceFd = fenceFd;
- } else if (fenceFd >= 0) {
- // we always own the fenceFd even when unlock failed
- close(fenceFd);
- }
-
- return toError(error);
-}
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace mapper
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.h b/graphics/mapper/2.0/default/Gralloc1Mapper.h
deleted file mode 100644
index 452afdf..0000000
--- a/graphics/mapper/2.0/default/Gralloc1Mapper.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
-#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
-
-#include "GrallocMapper.h"
-
-#include <hardware/gralloc1.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-class Gralloc1Mapper : public GrallocMapper {
- public:
- Gralloc1Mapper(const hw_module_t* module);
- ~Gralloc1Mapper();
-
- private:
- void initCapabilities();
-
- template <typename T>
- void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
- void initDispatch();
-
- static Error toError(int32_t error);
- static bool toYCbCrLayout(const android_flex_layout& flex,
- YCbCrLayout* outLayout);
- static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
-
- Error registerBuffer(buffer_handle_t bufferHandle) override;
- void unregisterBuffer(buffer_handle_t bufferHandle) override;
- Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- void** outData) override;
- Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- YCbCrLayout* outLayout) override;
- Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
-
- gralloc1_device_t* mDevice;
-
- struct {
- GRALLOC1_PFN_RETAIN retain;
- GRALLOC1_PFN_RELEASE release;
- GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
- GRALLOC1_PFN_LOCK lock;
- GRALLOC1_PFN_LOCK_FLEX lockFlex;
- GRALLOC1_PFN_UNLOCK unlock;
- } mDispatch;
-};
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace mapper
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp
deleted file mode 100644
index d16143d..0000000
--- a/graphics/mapper/2.0/default/GrallocMapper.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright 2016 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 "GrallocMapperPassthrough"
-
-#include "GrallocMapper.h"
-
-#include "Gralloc0Mapper.h"
-#include "Gralloc1Mapper.h"
-#include "GrallocBufferDescriptor.h"
-
-#include <inttypes.h>
-
-#include <log/log.h>
-#include <sync/sync.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
-namespace {
-
-class RegisteredHandlePool {
- public:
- bool add(buffer_handle_t bufferHandle) {
- std::lock_guard<std::mutex> lock(mMutex);
- return mHandles.insert(bufferHandle).second;
- }
-
- native_handle_t* pop(void* buffer) {
- auto bufferHandle = static_cast<native_handle_t*>(buffer);
-
- std::lock_guard<std::mutex> lock(mMutex);
- return mHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
- }
-
- buffer_handle_t get(const void* buffer) {
- auto bufferHandle = static_cast<buffer_handle_t>(buffer);
-
- std::lock_guard<std::mutex> lock(mMutex);
- return mHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
- }
-
- private:
- std::mutex mMutex;
- std::unordered_set<buffer_handle_t> mHandles;
-};
-
-// GraphicBufferMapper is expected to be valid (and leaked) during process
-// termination. We need to make sure IMapper, and in turn, gRegisteredHandles
-// are valid as well. Create the registered handle pool on the heap, and let
-// it leak for simplicity.
-//
-// However, there is no way to make sure gralloc0/gralloc1 are valid. Any use
-// of static/global object in gralloc0/gralloc1 that may have been destructed
-// is potentially broken.
-RegisteredHandlePool* gRegisteredHandles = new RegisteredHandlePool;
-
-} // anonymous namespace
-
-bool GrallocMapper::validateDescriptorInfo(
- const BufferDescriptorInfo& descriptorInfo) const {
- const uint64_t validUsageBits =
- BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
- BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET |
- BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET |
- BufferUsage::PROTECTED | BufferUsage::COMPOSER_CURSOR |
- BufferUsage::VIDEO_ENCODER | BufferUsage::CAMERA_OUTPUT |
- BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
- BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
- BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
- (mCapabilities.highUsageBits ? BufferUsage::VENDOR_MASK_HI
- : static_cast<BufferUsage>(0));
-
- if (!descriptorInfo.width || !descriptorInfo.height ||
- !descriptorInfo.layerCount) {
- return false;
- }
-
- if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
- return false;
- }
-
- if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
- return false;
- }
-
- if (descriptorInfo.usage & ~validUsageBits) {
- // could not fail as gralloc may use the reserved bits...
- ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
- descriptorInfo.usage & ~validUsageBits);
- }
-
- return true;
-}
-
-Return<void> GrallocMapper::createDescriptor(
- const BufferDescriptorInfo& descriptorInfo, createDescriptor_cb hidl_cb) {
- if (validateDescriptorInfo(descriptorInfo)) {
- hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo));
- } else {
- hidl_cb(Error::BAD_VALUE, BufferDescriptor());
- }
-
- return Void();
-}
-
-Return<void> GrallocMapper::importBuffer(const hidl_handle& rawHandle,
- importBuffer_cb hidl_cb) {
- // because of passthrough HALs, we must not generate an error when
- // rawHandle has been imported
-
- if (!rawHandle.getNativeHandle()) {
- hidl_cb(Error::BAD_BUFFER, nullptr);
- return Void();
- }
-
- native_handle_t* bufferHandle =
- native_handle_clone(rawHandle.getNativeHandle());
- if (!bufferHandle) {
- hidl_cb(Error::NO_RESOURCES, nullptr);
- return Void();
- }
-
- Error error = registerBuffer(bufferHandle);
- if (error != Error::NONE) {
- native_handle_close(bufferHandle);
- native_handle_delete(bufferHandle);
-
- hidl_cb(error, nullptr);
- return Void();
- }
-
- // The newly cloned handle is already registered? This can only happen
- // when a handle previously registered was native_handle_delete'd instead
- // of freeBuffer'd.
- if (!gRegisteredHandles->add(bufferHandle)) {
- ALOGE("handle %p has already been imported; potential fd leaking",
- bufferHandle);
- unregisterBuffer(bufferHandle);
- if (!mCapabilities.unregisterImplyDelete) {
- native_handle_close(bufferHandle);
- native_handle_delete(bufferHandle);
- }
-
- hidl_cb(Error::NO_RESOURCES, nullptr);
- return Void();
- }
-
- hidl_cb(Error::NONE, bufferHandle);
- return Void();
-}
-
-Return<Error> GrallocMapper::freeBuffer(void* buffer) {
- native_handle_t* bufferHandle = gRegisteredHandles->pop(buffer);
- if (!bufferHandle) {
- return Error::BAD_BUFFER;
- }
-
- unregisterBuffer(bufferHandle);
- if (!mCapabilities.unregisterImplyDelete) {
- native_handle_close(bufferHandle);
- native_handle_delete(bufferHandle);
- }
-
- return Error::NONE;
-}
-
-void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) {
- if (fenceFd < 0) {
- return;
- }
-
- const int warningTimeout = 3500;
- const int error = sync_wait(fenceFd, warningTimeout);
- if (error < 0 && errno == ETIME) {
- ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd,
- warningTimeout);
- sync_wait(fenceFd, -1);
- }
-}
-
-bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle,
- int* outFenceFd) {
- auto handle = fenceHandle.getNativeHandle();
- if (handle && handle->numFds > 1) {
- ALOGE("invalid fence handle with %d fds", handle->numFds);
- return false;
- }
-
- *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
- return true;
-}
-
-hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) {
- native_handle_t* handle = nullptr;
- if (fenceFd >= 0) {
- handle = native_handle_init(handleStorage, 1, 0);
- handle->data[0] = fenceFd;
- }
-
- return hidl_handle(handle);
-}
-
-Return<void> GrallocMapper::lock(void* buffer, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion,
- const hidl_handle& acquireFence,
- lock_cb hidl_cb) {
- buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
- if (!bufferHandle) {
- hidl_cb(Error::BAD_BUFFER, nullptr);
- return Void();
- }
-
- int fenceFd;
- if (!getFenceFd(acquireFence, &fenceFd)) {
- hidl_cb(Error::BAD_VALUE, nullptr);
- return Void();
- }
-
- void* data = nullptr;
- Error error =
- lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
-
- hidl_cb(error, data);
- return Void();
-}
-
-Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion,
- const hidl_handle& acquireFence,
- lockYCbCr_cb hidl_cb) {
- YCbCrLayout layout = {};
-
- buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
- if (!bufferHandle) {
- hidl_cb(Error::BAD_BUFFER, layout);
- return Void();
- }
-
- int fenceFd;
- if (!getFenceFd(acquireFence, &fenceFd)) {
- hidl_cb(Error::BAD_VALUE, layout);
- return Void();
- }
-
- Error error =
- lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout);
-
- hidl_cb(error, layout);
- return Void();
-}
-
-Return<void> GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) {
- buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
- if (!bufferHandle) {
- hidl_cb(Error::BAD_BUFFER, nullptr);
- return Void();
- }
-
- int fenceFd;
- Error error = unlockBuffer(bufferHandle, &fenceFd);
- if (error == Error::NONE) {
- NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
-
- hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
-
- if (fenceFd >= 0) {
- close(fenceFd);
- }
- } else {
- hidl_cb(error, nullptr);
- }
-
- return Void();
-}
-
-IMapper* HIDL_FETCH_IMapper(const char* /* name */) {
- const hw_module_t* module = nullptr;
- int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
- if (err) {
- ALOGE("failed to get gralloc module");
- return nullptr;
- }
-
- uint8_t major = (module->module_api_version >> 8) & 0xff;
- switch (major) {
- case 1:
- return new Gralloc1Mapper(module);
- case 0:
- return new Gralloc0Mapper(module);
- default:
- ALOGE("unknown gralloc module major version %d", major);
- return nullptr;
- }
-}
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace mapper
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/mapper/2.0/default/GrallocMapper.h b/graphics/mapper/2.0/default/GrallocMapper.h
deleted file mode 100644
index e876fe4..0000000
--- a/graphics/mapper/2.0/default/GrallocMapper.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
-#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <cutils/native_handle.h>
-
-#include <mutex>
-#include <unordered_set>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-class GrallocMapper : public IMapper {
- public:
- // IMapper interface
- Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
- createDescriptor_cb hidl_cb) override;
- Return<void> importBuffer(const hidl_handle& rawHandle,
- importBuffer_cb hidl_cb) override;
- Return<Error> freeBuffer(void* buffer) override;
- Return<void> lock(void* buffer, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion,
- const hidl_handle& acquireFence,
- lock_cb hidl_cb) override;
- Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion,
- const hidl_handle& acquireFence,
- lockYCbCr_cb hidl_cb) override;
- Return<void> unlock(void* buffer, unlock_cb hidl_cb) override;
-
- protected:
- static void waitFenceFd(int fenceFd, const char* logname);
-
- struct {
- bool highUsageBits;
- bool layeredBuffers;
- bool unregisterImplyDelete;
- } mCapabilities = {};
-
- private:
- virtual bool validateDescriptorInfo(
- const BufferDescriptorInfo& descriptorInfo) const;
-
- // Register a buffer. The handle is already cloned by the caller.
- virtual Error registerBuffer(buffer_handle_t bufferHandle) = 0;
-
- // Unregister a buffer. The handle is closed and deleted by the
- // callee if and only if mCapabilities.unregisterImplyDelete is set.
- virtual void unregisterBuffer(buffer_handle_t bufferHandle) = 0;
-
- // Lock a buffer. The fence is owned by the caller.
- virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- void** outData) = 0;
- virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
- const IMapper::Rect& accessRegion, int fenceFd,
- YCbCrLayout* outLayout) = 0;
-
- // Unlock a buffer. The returned fence is owned by the caller.
- virtual Error unlockBuffer(buffer_handle_t bufferHandle,
- int* outFenceFd) = 0;
-
- static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd);
- static hidl_handle getFenceHandle(int fenceFd, char* handleStorage);
-};
-
-extern "C" IMapper* HIDL_FETCH_IMapper(const char* name);
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace mapper
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
diff --git a/graphics/mapper/2.0/default/passthrough.cpp b/graphics/mapper/2.0/default/passthrough.cpp
new file mode 100644
index 0000000..e18b88f
--- /dev/null
+++ b/graphics/mapper/2.0/default/passthrough.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <mapper-passthrough/2.0/GrallocLoader.h>
+
+using android::hardware::graphics::mapper::V2_0::IMapper;
+using android::hardware::graphics::mapper::V2_0::passthrough::GrallocLoader;
+
+extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
+ return GrallocLoader::load();
+}
diff --git a/graphics/mapper/2.0/utils/OWNERS b/graphics/mapper/2.0/utils/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/mapper/2.0/utils/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/mapper/2.0/utils/hal/Android.bp b/graphics/mapper/2.0/utils/hal/Android.bp
new file mode 100644
index 0000000..5610a69
--- /dev/null
+++ b/graphics/mapper/2.0/utils/hal/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2018 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.
+
+cc_library_headers {
+ name: "android.hardware.graphics.mapper@2.0-hal",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ shared_libs: [
+ "android.hardware.graphics.mapper@2.0",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.mapper@2.0",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
new file mode 100644
index 0000000..5ad2a65
--- /dev/null
+++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Mapper.h included without LOG_TAG"
+#endif
+
+#include <memory>
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/MapperHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace hal {
+
+namespace detail {
+
+// MapperImpl implements V2_*::IMapper on top of V2_*::hal::MapperHal
+template <typename Interface, typename Hal>
+class MapperImpl : public Interface {
+ public:
+ bool init(std::unique_ptr<Hal> hal) {
+ mHal = std::move(hal);
+ return true;
+ }
+
+ // IMapper 2.0 interface
+
+ Return<void> createDescriptor(const V2_0::IMapper::BufferDescriptorInfo& descriptorInfo,
+ IMapper::createDescriptor_cb hidl_cb) override {
+ BufferDescriptor descriptor;
+ Error error = mHal->createDescriptor(descriptorInfo, &descriptor);
+ hidl_cb(error, descriptor);
+ return Void();
+ }
+
+ Return<void> importBuffer(const hidl_handle& rawHandle,
+ IMapper::importBuffer_cb hidl_cb) override {
+ if (!rawHandle.getNativeHandle()) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ native_handle_t* bufferHandle = nullptr;
+ Error error = mHal->importBuffer(rawHandle.getNativeHandle(), &bufferHandle);
+ if (error != Error::NONE) {
+ hidl_cb(error, nullptr);
+ return Void();
+ }
+
+ void* buffer = addImportedBuffer(bufferHandle);
+ if (!buffer) {
+ mHal->freeBuffer(bufferHandle);
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ hidl_cb(error, buffer);
+ return Void();
+ }
+
+ Return<Error> freeBuffer(void* buffer) override {
+ native_handle_t* bufferHandle = removeImportedBuffer(buffer);
+ if (!bufferHandle) {
+ return Error::BAD_BUFFER;
+ }
+
+ return mHal->freeBuffer(bufferHandle);
+ }
+
+ Return<void> lock(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence, IMapper::lock_cb hidl_cb) override {
+ const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+ if (!bufferHandle) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ base::unique_fd fenceFd;
+ Error error = getFenceFd(acquireFence, &fenceFd);
+ if (error != Error::NONE) {
+ hidl_cb(error, nullptr);
+ return Void();
+ }
+
+ void* data = nullptr;
+ error = mHal->lock(bufferHandle, cpuUsage, accessRegion, std::move(fenceFd), &data);
+ hidl_cb(error, data);
+ return Void();
+ }
+
+ Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ IMapper::lockYCbCr_cb hidl_cb) override {
+ const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+ if (!bufferHandle) {
+ hidl_cb(Error::BAD_BUFFER, YCbCrLayout{});
+ return Void();
+ }
+
+ base::unique_fd fenceFd;
+ Error error = getFenceFd(acquireFence, &fenceFd);
+ if (error != Error::NONE) {
+ hidl_cb(error, YCbCrLayout{});
+ return Void();
+ }
+
+ YCbCrLayout layout{};
+ error = mHal->lockYCbCr(bufferHandle, cpuUsage, accessRegion, std::move(fenceFd), &layout);
+ hidl_cb(error, layout);
+ return Void();
+ }
+
+ Return<void> unlock(void* buffer, IMapper::unlock_cb hidl_cb) override {
+ const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+ if (!bufferHandle) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ base::unique_fd fenceFd;
+ Error error = mHal->unlock(bufferHandle, &fenceFd);
+ if (error != Error::NONE) {
+ hidl_cb(error, nullptr);
+ return Void();
+ }
+
+ NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+ hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+ return Void();
+ }
+
+ protected:
+ // these functions can be overriden to do true imported buffer management
+ virtual void* addImportedBuffer(native_handle_t* bufferHandle) {
+ return static_cast<void*>(bufferHandle);
+ }
+
+ virtual native_handle_t* removeImportedBuffer(void* buffer) {
+ return static_cast<native_handle_t*>(buffer);
+ }
+
+ virtual const native_handle_t* getImportedBuffer(void* buffer) const {
+ return static_cast<const native_handle_t*>(buffer);
+ }
+
+ // convert fenceFd to or from hidl_handle
+ static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) {
+ auto handle = fenceHandle.getNativeHandle();
+ if (handle && handle->numFds > 1) {
+ ALOGE("invalid fence handle with %d fds", handle->numFds);
+ return Error::BAD_VALUE;
+ }
+
+ int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+ if (fenceFd >= 0) {
+ fenceFd = dup(fenceFd);
+ if (fenceFd < 0) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ outFenceFd->reset(fenceFd);
+
+ return Error::NONE;
+ }
+
+ static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) {
+ native_handle_t* handle = nullptr;
+ if (fenceFd >= 0) {
+ handle = native_handle_init(handleStorage, 1, 0);
+ handle->data[0] = fenceFd;
+ }
+
+ return hidl_handle(handle);
+ }
+
+ std::unique_ptr<Hal> mHal;
+};
+
+} // namespace detail
+
+using Mapper = detail::MapperImpl<IMapper, MapperHal>;
+
+} // namespace hal
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h
new file mode 100644
index 0000000..ab2e5cf
--- /dev/null
+++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace hal {
+
+class MapperHal {
+ public:
+ virtual ~MapperHal() = default;
+
+ // create a BufferDescriptor
+ virtual Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) = 0;
+
+ // import a raw handle owned by the caller
+ virtual Error importBuffer(const native_handle_t* rawHandle,
+ native_handle_t** outBufferHandle) = 0;
+
+ // free an imported buffer handle
+ virtual Error freeBuffer(native_handle_t* bufferHandle) = 0;
+
+ // lock a buffer
+ virtual Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+ void** outData) = 0;
+
+ // lock a YCbCr buffer
+ virtual Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+ YCbCrLayout* outLayout) = 0;
+
+ // unlock a buffer
+ virtual Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) = 0;
+};
+
+} // namespace hal
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.0/utils/passthrough/Android.bp b/graphics/mapper/2.0/utils/passthrough/Android.bp
new file mode 100644
index 0000000..4f700c8
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2016 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.
+
+cc_library_headers {
+ name: "android.hardware.graphics.mapper@2.0-passthrough",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ shared_libs: [
+ "android.hardware.graphics.mapper@2.0",
+ "libhardware",
+ "libsync",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.mapper@2.0",
+ "libhardware",
+ "libsync",
+ ],
+ header_libs: [
+ "android.hardware.graphics.mapper@2.0-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.mapper@2.0-hal",
+ ],
+ export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+ name: "android.hardware.graphics.mapper@2.0-passthrough_headers",
+ vendor: true,
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h
new file mode 100644
index 0000000..7369ac7
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Gralloc0Hal.h included without LOG_TAG"
+#endif
+
+#include <inttypes.h>
+
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/MapperHal.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
+#include <sync/sync.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_0::BufferUsage;
+
+// Gralloc0HalImpl implements V2_*::hal::MapperHal on top of gralloc0
+template <typename Hal>
+class Gralloc0HalImpl : public Hal {
+ public:
+ bool initWithModule(const hw_module_t* module) {
+ mModule = reinterpret_cast<const gralloc_module_t*>(module);
+ mMinor = module->module_api_version & 0xff;
+ return true;
+ }
+
+ Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) override {
+ if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
+ return Error::BAD_VALUE;
+ }
+
+ if (descriptorInfo.layerCount != 1) {
+ return Error::UNSUPPORTED;
+ }
+
+ if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+ return Error::BAD_VALUE;
+ }
+
+ const uint64_t validUsageBits = getValidBufferUsageMask();
+ if (descriptorInfo.usage & ~validUsageBits) {
+ ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+ descriptorInfo.usage & ~validUsageBits);
+ }
+
+ *outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
+
+ return Error::NONE;
+ }
+
+ Error importBuffer(const native_handle_t* rawHandle,
+ native_handle_t** outBufferHandle) override {
+ native_handle_t* bufferHandle = native_handle_clone(rawHandle);
+ if (!bufferHandle) {
+ return Error::NO_RESOURCES;
+ }
+
+ if (mModule->registerBuffer(mModule, bufferHandle)) {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ return Error::BAD_BUFFER;
+ }
+
+ *outBufferHandle = bufferHandle;
+
+ return Error::NONE;
+ }
+
+ Error freeBuffer(native_handle_t* bufferHandle) override {
+ if (mModule->unregisterBuffer(mModule, bufferHandle)) {
+ return Error::BAD_BUFFER;
+ }
+
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ return Error::NONE;
+ }
+
+ Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+ void** outData) override {
+ int result;
+ void* data = nullptr;
+ if (mMinor >= 3 && mModule->lockAsync) {
+ result = mModule->lockAsync(mModule, bufferHandle, cpuUsage, accessRegion.left,
+ accessRegion.top, accessRegion.width, accessRegion.height,
+ &data, fenceFd.release());
+ } else {
+ waitFenceFd(fenceFd, "Gralloc0Hal::lock");
+
+ result =
+ mModule->lock(mModule, bufferHandle, cpuUsage, accessRegion.left, accessRegion.top,
+ accessRegion.width, accessRegion.height, &data);
+ }
+
+ if (result) {
+ return Error::BAD_VALUE;
+ }
+
+ *outData = data;
+ return Error::NONE;
+ }
+
+ Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+ YCbCrLayout* outLayout) override {
+ int result;
+ android_ycbcr ycbcr = {};
+ if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
+ result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage, accessRegion.left,
+ accessRegion.top, accessRegion.width,
+ accessRegion.height, &ycbcr, fenceFd.release());
+ } else {
+ waitFenceFd(fenceFd, "Gralloc0Hal::lockYCbCr");
+
+ if (mModule->lock_ycbcr) {
+ result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage, accessRegion.left,
+ accessRegion.top, accessRegion.width,
+ accessRegion.height, &ycbcr);
+ } else {
+ result = -EINVAL;
+ }
+ }
+
+ if (result) {
+ return Error::BAD_VALUE;
+ }
+
+ outLayout->y = ycbcr.y;
+ outLayout->cb = ycbcr.cb;
+ outLayout->cr = ycbcr.cr;
+ outLayout->yStride = ycbcr.ystride;
+ outLayout->cStride = ycbcr.cstride;
+ outLayout->chromaStep = ycbcr.chroma_step;
+ return Error::NONE;
+ }
+
+ Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
+ int result;
+ int fenceFd = -1;
+ if (mMinor >= 3 && mModule->unlockAsync) {
+ result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
+ } else {
+ result = mModule->unlock(mModule, bufferHandle);
+ }
+
+ // we always own the fenceFd even when unlock failed
+ outFenceFd->reset(fenceFd);
+ return result ? Error::BAD_VALUE : Error::NONE;
+ }
+
+ protected:
+ virtual uint64_t getValidBufferUsageMask() const {
+ return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
+ BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
+ BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
+ BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
+ BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+ BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+ BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK;
+ }
+
+ static void waitFenceFd(const base::unique_fd& fenceFd, const char* logname) {
+ if (fenceFd < 0) {
+ return;
+ }
+
+ const int warningTimeout = 3500;
+ const int error = sync_wait(fenceFd, warningTimeout);
+ if (error < 0 && errno == ETIME) {
+ ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd.get(), warningTimeout);
+ sync_wait(fenceFd, -1);
+ }
+ }
+
+ const gralloc_module_t* mModule = nullptr;
+ uint8_t mMinor = 0;
+};
+
+} // namespace detail
+
+using Gralloc0Hal = detail::Gralloc0HalImpl<hal::MapperHal>;
+
+} // namespace passthrough
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
new file mode 100644
index 0000000..d9beb4f
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Gralloc1Hal.h included without LOG_TAG"
+#endif
+
+#include <inttypes.h>
+
+#include <vector>
+
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/MapperHal.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_0::BufferUsage;
+
+// Gralloc1HalImpl implements V2_*::hal::MapperHal on top of gralloc1
+template <typename Hal>
+class Gralloc1HalImpl : public Hal {
+ public:
+ ~Gralloc1HalImpl() {
+ if (mDevice) {
+ gralloc1_close(mDevice);
+ }
+ }
+
+ bool initWithModule(const hw_module_t* module) {
+ int result = gralloc1_open(module, &mDevice);
+ if (result) {
+ ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+ mDevice = nullptr;
+ return false;
+ }
+
+ initCapabilities();
+
+ if (!initDispatch()) {
+ gralloc1_close(mDevice);
+ mDevice = nullptr;
+ return false;
+ }
+
+ return true;
+ }
+
+ Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) override {
+ if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
+ return Error::BAD_VALUE;
+ }
+
+ if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount != 1) {
+ return Error::UNSUPPORTED;
+ }
+
+ if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+ return Error::BAD_VALUE;
+ }
+
+ const uint64_t validUsageBits = getValidBufferUsageMask();
+ if (descriptorInfo.usage & ~validUsageBits) {
+ ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+ descriptorInfo.usage & ~validUsageBits);
+ }
+
+ *outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
+
+ return Error::NONE;
+ }
+
+ Error importBuffer(const native_handle_t* rawHandle,
+ native_handle_t** outBufferHandle) override {
+ native_handle_t* bufferHandle = native_handle_clone(rawHandle);
+ if (!bufferHandle) {
+ return Error::NO_RESOURCES;
+ }
+
+ int32_t error = mDispatch.retain(mDevice, bufferHandle);
+ if (error != GRALLOC1_ERROR_NONE) {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ return toError(error);
+ }
+
+ *outBufferHandle = bufferHandle;
+
+ return Error::NONE;
+ }
+
+ Error freeBuffer(native_handle_t* bufferHandle) override {
+ int32_t error = mDispatch.release(mDevice, bufferHandle);
+ if (error == GRALLOC1_ERROR_NONE && !mCapabilities.releaseImplyDelete) {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ }
+ return toError(error);
+ }
+
+ Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+ void** outData) override {
+ const uint64_t consumerUsage =
+ cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+ const auto accessRect = asGralloc1Rect(accessRegion);
+ void* data = nullptr;
+ int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
+ &data, fenceFd.release());
+ if (error == GRALLOC1_ERROR_NONE) {
+ *outData = data;
+ }
+
+ return toError(error);
+ }
+
+ Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+ YCbCrLayout* outLayout) override {
+ // prepare flex layout
+ android_flex_layout flex = {};
+ int32_t error = mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
+ if (error != GRALLOC1_ERROR_NONE) {
+ return toError(error);
+ }
+ std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
+ flex.planes = flexPlanes.data();
+
+ const uint64_t consumerUsage =
+ cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+ const auto accessRect = asGralloc1Rect(accessRegion);
+ error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
+ &flex, fenceFd.release());
+ if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
+ ALOGD("unable to convert android_flex_layout to YCbCrLayout");
+ // undo the lock
+ unlock(bufferHandle, &fenceFd);
+ error = GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ return toError(error);
+ }
+
+ Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
+ int fenceFd = -1;
+ int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+
+ // we always own the fenceFd even when unlock failed
+ outFenceFd->reset(fenceFd);
+ return toError(error);
+ }
+
+ protected:
+ virtual void initCapabilities() {
+ uint32_t count = 0;
+ mDevice->getCapabilities(mDevice, &count, nullptr);
+
+ std::vector<int32_t> capabilities(count);
+ mDevice->getCapabilities(mDevice, &count, capabilities.data());
+ capabilities.resize(count);
+
+ for (auto capability : capabilities) {
+ switch (capability) {
+ case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
+ mCapabilities.layeredBuffers = true;
+ break;
+ case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
+ mCapabilities.releaseImplyDelete = true;
+ break;
+ }
+ }
+ }
+
+ template <typename T>
+ bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
+ auto pfn = mDevice->getFunction(mDevice, desc);
+ if (pfn) {
+ *outPfn = reinterpret_cast<T>(pfn);
+ return true;
+ } else {
+ ALOGE("failed to get gralloc1 function %d", desc);
+ return false;
+ }
+ }
+
+ virtual bool initDispatch() {
+ if (!initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain) ||
+ !initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release) ||
+ !initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES, &mDispatch.getNumFlexPlanes) ||
+ !initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock) ||
+ !initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex) ||
+ !initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual uint64_t getValidBufferUsageMask() const {
+ return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
+ BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
+ BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
+ BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
+ BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+ BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+ BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
+ BufferUsage::VENDOR_MASK_HI;
+ }
+
+ static Error toError(int32_t error) {
+ switch (error) {
+ case GRALLOC1_ERROR_NONE:
+ return Error::NONE;
+ case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+ return Error::BAD_DESCRIPTOR;
+ case GRALLOC1_ERROR_BAD_HANDLE:
+ return Error::BAD_BUFFER;
+ case GRALLOC1_ERROR_BAD_VALUE:
+ return Error::BAD_VALUE;
+ case GRALLOC1_ERROR_NOT_SHARED:
+ return Error::NONE; // this is fine
+ case GRALLOC1_ERROR_NO_RESOURCES:
+ return Error::NO_RESOURCES;
+ case GRALLOC1_ERROR_UNDEFINED:
+ case GRALLOC1_ERROR_UNSUPPORTED:
+ default:
+ return Error::UNSUPPORTED;
+ }
+ }
+
+ static bool toYCbCrLayout(const android_flex_layout& flex, YCbCrLayout* outLayout) {
+ // must be YCbCr
+ if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
+ return false;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ const auto& plane = flex.planes[i];
+ // must have 8-bit depth
+ if (plane.bits_per_component != 8 || plane.bits_used != 8) {
+ return false;
+ }
+
+ if (plane.component == FLEX_COMPONENT_Y) {
+ // Y must not be interleaved
+ if (plane.h_increment != 1) {
+ return false;
+ }
+ } else {
+ // Cb and Cr can be interleaved
+ if (plane.h_increment != 1 && plane.h_increment != 2) {
+ return false;
+ }
+ }
+
+ if (!plane.v_increment) {
+ return false;
+ }
+ }
+
+ if (flex.planes[0].component != FLEX_COMPONENT_Y ||
+ flex.planes[1].component != FLEX_COMPONENT_Cb ||
+ flex.planes[2].component != FLEX_COMPONENT_Cr) {
+ return false;
+ }
+
+ const auto& y = flex.planes[0];
+ const auto& cb = flex.planes[1];
+ const auto& cr = flex.planes[2];
+
+ if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
+ return false;
+ }
+
+ outLayout->y = y.top_left;
+ outLayout->cb = cb.top_left;
+ outLayout->cr = cr.top_left;
+ outLayout->yStride = y.v_increment;
+ outLayout->cStride = cb.v_increment;
+ outLayout->chromaStep = cb.h_increment;
+
+ return true;
+ }
+
+ static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect) {
+ return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
+ }
+
+ gralloc1_device_t* mDevice = nullptr;
+
+ struct {
+ bool layeredBuffers;
+ bool releaseImplyDelete;
+ } mCapabilities = {};
+
+ struct {
+ GRALLOC1_PFN_RETAIN retain;
+ GRALLOC1_PFN_RELEASE release;
+ GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+ GRALLOC1_PFN_LOCK lock;
+ GRALLOC1_PFN_LOCK_FLEX lockFlex;
+ GRALLOC1_PFN_UNLOCK unlock;
+ } mDispatch = {};
+};
+
+} // namespace detail
+
+using Gralloc1Hal = detail::Gralloc1HalImpl<hal::MapperHal>;
+
+} // namespace passthrough
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h
similarity index 84%
rename from graphics/mapper/2.0/default/GrallocBufferDescriptor.h
rename to graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h
index 9b5ab04..4c477e1 100644
--- a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
-#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
+#pragma once
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
@@ -24,7 +23,7 @@
namespace graphics {
namespace mapper {
namespace V2_0 {
-namespace implementation {
+namespace passthrough {
using android::hardware::graphics::common::V1_0::PixelFormat;
@@ -50,9 +49,8 @@
return descriptor;
}
-inline bool grallocDecodeBufferDescriptor(
- const BufferDescriptor& descriptor,
- IMapper::BufferDescriptorInfo* outDescriptorInfo) {
+inline bool grallocDecodeBufferDescriptor(const BufferDescriptor& descriptor,
+ IMapper::BufferDescriptorInfo* outDescriptorInfo) {
if (descriptor.size() != grallocBufferDescriptorSize ||
descriptor[0] != grallocBufferDescriptorMagicVersion) {
return false;
@@ -69,11 +67,9 @@
return true;
}
-} // namespace implementation
+} // namespace passthrough
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
new file mode 100644
index 0000000..e8b1b4b
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "GrallocLoader.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <unordered_set>
+
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/Mapper.h>
+#include <mapper-passthrough/2.0/Gralloc0Hal.h>
+#include <mapper-passthrough/2.0/Gralloc1Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+class GrallocImportedBufferPool {
+ public:
+ static GrallocImportedBufferPool& getInstance() {
+ // GraphicBufferMapper in framework is expected to be valid (and
+ // leaked) during process termination. We need to make sure IMapper,
+ // and in turn, GrallocImportedBufferPool is valid as well. Create
+ // imported buffer pool on the heap (and let it leak) for the purpose.
+ // Besides, all IMapper instances must share the same pool. Make it a
+ // singleton.
+ //
+ // However, there is no way to make sure gralloc0/gralloc1 are valid
+ // during process termination. Any use of static/global object in
+ // gralloc0/gralloc1 that may be destructed during process termination
+ // is potentially broken.
+ static GrallocImportedBufferPool* singleton = new GrallocImportedBufferPool;
+ return *singleton;
+ }
+
+ void* add(native_handle_t* bufferHandle) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr;
+ }
+
+ native_handle_t* remove(void* buffer) {
+ auto bufferHandle = static_cast<native_handle_t*>(buffer);
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
+ }
+
+ const native_handle_t* get(void* buffer) {
+ auto bufferHandle = static_cast<const native_handle_t*>(buffer);
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
+ }
+
+ private:
+ std::mutex mMutex;
+ std::unordered_set<const native_handle_t*> mBufferHandles;
+};
+
+// Inherit from V2_*::hal::Mapper and override imported buffer management functions
+template <typename T>
+class GrallocMapper : public T {
+ protected:
+ void* addImportedBuffer(native_handle_t* bufferHandle) override {
+ return GrallocImportedBufferPool::getInstance().add(bufferHandle);
+ }
+
+ native_handle_t* removeImportedBuffer(void* buffer) override {
+ return GrallocImportedBufferPool::getInstance().remove(buffer);
+ }
+
+ const native_handle_t* getImportedBuffer(void* buffer) const override {
+ return GrallocImportedBufferPool::getInstance().get(buffer);
+ }
+};
+
+class GrallocLoader {
+ public:
+ static IMapper* load() {
+ const hw_module_t* module = loadModule();
+ if (!module) {
+ return nullptr;
+ }
+ auto hal = createHal(module);
+ if (!hal) {
+ return nullptr;
+ }
+ return createMapper(std::move(hal));
+ }
+
+ // load the gralloc module
+ static const hw_module_t* loadModule() {
+ const hw_module_t* module;
+ int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (error) {
+ ALOGE("failed to get gralloc module");
+ return nullptr;
+ }
+
+ return module;
+ }
+
+ // return the major api version of the module
+ static int getModuleMajorApiVersion(const hw_module_t* module) {
+ return (module->module_api_version >> 8) & 0xff;
+ }
+
+ // create a MapperHal instance
+ static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) {
+ int major = getModuleMajorApiVersion(module);
+ switch (major) {
+ case 1: {
+ auto hal = std::make_unique<Gralloc1Hal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+ case 0: {
+ auto hal = std::make_unique<Gralloc0Hal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+ default:
+ ALOGE("unknown gralloc module major version %d", major);
+ return nullptr;
+ }
+ }
+
+ // create an IAllocator instance
+ static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) {
+ auto mapper = std::make_unique<GrallocMapper<hal::Mapper>>();
+ return mapper->init(std::move(hal)) ? mapper.release() : nullptr;
+ }
+};
+
+} // namespace passthrough
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.0/utils/vts/Android.bp b/graphics/mapper/2.0/utils/vts/Android.bp
new file mode 100644
index 0000000..1aa3185
--- /dev/null
+++ b/graphics/mapper/2.0/utils/vts/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2016 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.
+//
+
+cc_library_static {
+ name: "android.hardware.graphics.mapper@2.0-vts",
+ defaults: ["hidl_defaults"],
+ srcs: ["MapperVts.cpp"],
+ cflags: [
+ "-O0",
+ "-g",
+ ],
+ shared_libs: [
+ "libutils",
+ ],
+ static_libs: [
+ "VtsHalHidlTargetTestBase",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.mapper@2.0",
+ ],
+ export_static_lib_headers: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.mapper@2.0",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp b/graphics/mapper/2.0/utils/vts/MapperVts.cpp
similarity index 64%
rename from graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
rename to graphics/mapper/2.0/utils/vts/MapperVts.cpp
index 671c4b1..d08ac56 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
+++ b/graphics/mapper/2.0/utils/vts/MapperVts.cpp
@@ -14,28 +14,26 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
+#include <mapper-vts/2.0/MapperVts.h>
-#include "VtsHalGraphicsMapperTestUtils.h"
+#include <VtsHalHidlTargetTestBase.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
-namespace tests {
+namespace vts {
-Gralloc::Gralloc() {
- init();
+Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
+ init(allocatorServiceName, mapperServiceName);
}
-void Gralloc::init() {
- mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(
- GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>());
+void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
+ mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
- mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(
- GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>());
+ mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
}
@@ -50,8 +48,7 @@
for (auto bufferHandle : mImportedBuffers) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
- EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer))
- << "failed to free buffer " << buffer;
+ EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
}
mImportedBuffers.clear();
}
@@ -62,15 +59,13 @@
std::string Gralloc::dumpDebugInfo() {
std::string debugInfo;
- mAllocator->dumpDebugInfo(
- [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+ mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
return debugInfo;
}
const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
- const native_handle_t* bufferHandle =
- native_handle_clone(rawHandle.getNativeHandle());
+ const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
EXPECT_NE(nullptr, bufferHandle);
if (bufferHandle) {
@@ -80,24 +75,22 @@
return bufferHandle;
}
-std::vector<const native_handle_t*> Gralloc::allocate(
- const BufferDescriptor& descriptor, uint32_t count, bool import,
- uint32_t* outStride) {
+std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
+ uint32_t count, bool import,
+ uint32_t* outStride) {
std::vector<const native_handle_t*> bufferHandles;
bufferHandles.reserve(count);
mAllocator->allocate(
- descriptor, count, [&](const auto& tmpError, const auto& tmpStride,
- const auto& tmpBuffers) {
+ descriptor, count,
+ [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
for (uint32_t i = 0; i < count; i++) {
if (import) {
- ASSERT_NO_FATAL_FAILURE(
- bufferHandles.push_back(importBuffer(tmpBuffers[i])));
+ ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(importBuffer(tmpBuffers[i])));
} else {
- ASSERT_NO_FATAL_FAILURE(
- bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
+ ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
}
}
@@ -113,9 +106,8 @@
return bufferHandles;
}
-const native_handle_t* Gralloc::allocate(
- const IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
- uint32_t* outStride) {
+const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ bool import, uint32_t* outStride) {
BufferDescriptor descriptor = createDescriptor(descriptorInfo);
if (::testing::Test::HasFatalFailure()) {
return nullptr;
@@ -133,26 +125,23 @@
return mMapper;
}
-BufferDescriptor Gralloc::createDescriptor(
- const IMapper::BufferDescriptorInfo& descriptorInfo) {
+BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
BufferDescriptor descriptor;
- mMapper->createDescriptor(
- descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
- descriptor = tmpDescriptor;
- });
+ mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
+ descriptor = tmpDescriptor;
+ });
return descriptor;
}
const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
const native_handle_t* bufferHandle = nullptr;
- mMapper->importBuffer(
- rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to import buffer %p"
- << rawHandle.getNativeHandle();
- bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
- });
+ mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+ ASSERT_EQ(Error::NONE, tmpError)
+ << "failed to import buffer %p" << rawHandle.getNativeHandle();
+ bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+ });
if (bufferHandle) {
mImportedBuffers.insert(bufferHandle);
@@ -189,8 +178,7 @@
void* data = nullptr;
mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
[&](const auto& tmpError, const auto& tmpData) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to lock buffer " << buffer;
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
data = tmpData;
});
@@ -201,10 +189,8 @@
return data;
}
-YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle,
- uint64_t cpuUsage,
- const IMapper::Rect& accessRegion,
- int acquireFence) {
+YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int acquireFence) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
@@ -234,29 +220,25 @@
auto buffer = const_cast<native_handle_t*>(bufferHandle);
int releaseFence = -1;
- mMapper->unlock(
- buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer "
- << buffer;
+ mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " << buffer;
- auto fenceHandle = tmpReleaseFence.getNativeHandle();
- if (fenceHandle) {
- ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle "
- << fenceHandle;
- if (fenceHandle->numFds == 1) {
- releaseFence = dup(fenceHandle->data[0]);
- ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
- } else {
- ASSERT_EQ(0, fenceHandle->numFds)
- << " invalid fence handle " << fenceHandle;
- }
+ auto fenceHandle = tmpReleaseFence.getNativeHandle();
+ if (fenceHandle) {
+ ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
+ if (fenceHandle->numFds == 1) {
+ releaseFence = dup(fenceHandle->data[0]);
+ ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
+ } else {
+ ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
}
- });
+ }
+ });
return releaseFence;
}
-} // namespace tests
+} // namespace vts
} // namespace V2_0
} // namespace mapper
} // namespace graphics
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h b/graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
similarity index 64%
rename from graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
rename to graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
index 9cf60a3..6c2c9a6 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
+++ b/graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#ifndef VTS_HAL_GRAPHICS_MAPPER_UTILS
-#define VTS_HAL_GRAPHICS_MAPPER_UTILS
+#pragma once
+#include <string>
#include <unordered_set>
+#include <vector>
-#include <VtsHalHidlTargetTestEnvBase.h>
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <utils/StrongPointer.h>
@@ -29,14 +29,15 @@
namespace graphics {
namespace mapper {
namespace V2_0 {
-namespace tests {
+namespace vts {
using android::hardware::graphics::allocator::V2_0::IAllocator;
// A wrapper to IAllocator and IMapper.
class Gralloc {
public:
- Gralloc();
+ Gralloc(const std::string& allocatorServiceName = "default",
+ const std::string& mapperServiceName = "default");
~Gralloc();
// IAllocator methods
@@ -49,19 +50,16 @@
// is true, the returned buffers are also imported into the mapper.
//
// Either case, the returned buffers must be freed with freeBuffer.
- std::vector<const native_handle_t*> allocate(
- const BufferDescriptor& descriptor, uint32_t count, bool import = true,
- uint32_t* outStride = nullptr);
- const native_handle_t* allocate(
- const IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
- uint32_t* outStride = nullptr);
+ std::vector<const native_handle_t*> allocate(const BufferDescriptor& descriptor, uint32_t count,
+ bool import = true, uint32_t* outStride = nullptr);
+ const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ bool import = true, uint32_t* outStride = nullptr);
// IMapper methods
sp<IMapper> getMapper() const;
- BufferDescriptor createDescriptor(
- const IMapper::BufferDescriptorInfo& descriptorInfo);
+ BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
const native_handle_t* importBuffer(const hidl_handle& rawHandle);
void freeBuffer(const native_handle_t* bufferHandle);
@@ -71,13 +69,12 @@
// with each of these functions.
void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int acquireFence);
- YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle,
- uint64_t cpuUsage, const IMapper::Rect& accessRegion,
- int acquireFence);
+ YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int acquireFence);
int unlock(const native_handle_t* bufferHandle);
private:
- void init();
+ void init(const std::string& allocatorServiceName, const std::string& mapperServiceName);
const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
sp<IAllocator> mAllocator;
@@ -89,26 +86,9 @@
std::unordered_set<const native_handle_t*> mImportedBuffers;
};
-// Test environment for graphics.mapper.
-class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static GraphicsMapperHidlEnvironment* Instance() {
- static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override {
- registerTestService<IAllocator>();
- registerTestService<IMapper>();
- }
-};
-
-} // namespace tests
+} // namespace vts
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android
-
-#endif // VTS_HAL_GRAPHICS_MAPPER_UTILS
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index ac6cb47..969317a 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -14,39 +14,14 @@
// limitations under the License.
//
-cc_library_static {
- name: "libVtsHalGraphicsMapperTestUtils",
- defaults: ["hidl_defaults"],
- srcs: ["VtsHalGraphicsMapperTestUtils.cpp"],
- shared_libs: [
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.mapper@2.0",
- ],
- static_libs: [
- "VtsHalHidlTargetTestBase",
- ],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-O0",
- "-g",
- ],
- export_include_dirs: ["."],
-}
-
cc_test {
name: "VtsHalGraphicsMapperV2_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalGraphicsMapperV2_0TargetTest.cpp"],
- shared_libs: [
- "libsync",
- ],
static_libs: [
"android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.common@1.0",
- "libVtsHalGraphicsMapperTestUtils",
- "libnativehelper",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.0-vts",
],
}
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
index 1f94898..aa9beff 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
@@ -18,37 +18,54 @@
#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
-#include <sync/sync.h>
-#include "VtsHalGraphicsMapperTestUtils.h"
+#include <mapper-vts/2.0/MapperVts.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
-namespace tests {
+namespace vts {
namespace {
using android::hardware::graphics::common::V1_0::BufferUsage;
using android::hardware::graphics::common::V1_0::PixelFormat;
+// Test environment for graphics.mapper.
+class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static GraphicsMapperHidlEnvironment* Instance() {
+ static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
+ return instance;
+ }
+
+ virtual void registerTestServices() override {
+ registerTestService<IAllocator>();
+ registerTestService<IMapper>();
+ }
+};
+
class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(
+ mGralloc = std::make_unique<Gralloc>(
+ GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
+ GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
- mDummyDescriptorInfo.width = 64;
- mDummyDescriptorInfo.height = 64;
- mDummyDescriptorInfo.layerCount = 1;
- mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
- mDummyDescriptorInfo.usage = static_cast<uint64_t>(
- BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
- }
+ mDummyDescriptorInfo.width = 64;
+ mDummyDescriptorInfo.height = 64;
+ mDummyDescriptorInfo.layerCount = 1;
+ mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+ mDummyDescriptorInfo.usage =
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+ }
- void TearDown() override {}
+ void TearDown() override {}
- std::unique_ptr<Gralloc> mGralloc;
- IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
+ std::unique_ptr<Gralloc> mGralloc;
+ IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
};
/**
@@ -63,18 +80,16 @@
*/
TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
BufferDescriptor descriptor;
- ASSERT_NO_FATAL_FAILURE(
- descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
+ ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
for (uint32_t count = 0; count < 5; count++) {
std::vector<const native_handle_t*> bufferHandles;
uint32_t stride;
- ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate(
- descriptor, count, false, &stride));
+ ASSERT_NO_FATAL_FAILURE(bufferHandles =
+ mGralloc->allocate(descriptor, count, false, &stride));
if (count >= 1) {
- EXPECT_LE(mDummyDescriptorInfo.width, stride)
- << "invalid buffer stride";
+ EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
}
for (auto bufferHandle : bufferHandles) {
@@ -89,10 +104,10 @@
TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
// this assumes any valid descriptor is non-empty
BufferDescriptor descriptor;
- mGralloc->getAllocator()->allocate(
- descriptor, 1, [&](const auto& tmpError, const auto&, const auto&) {
- EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
- });
+ mGralloc->getAllocator()->allocate(descriptor, 1,
+ [&](const auto& tmpError, const auto&, const auto&) {
+ EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
+ });
}
/**
@@ -122,11 +137,9 @@
TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
auto info = mDummyDescriptorInfo;
info.width = 0;
- mGralloc->getMapper()->createDescriptor(
- info, [&](const auto& tmpError, const auto&) {
- EXPECT_EQ(Error::BAD_VALUE, tmpError)
- << "createDescriptor did not fail with BAD_VALUE";
- });
+ mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE";
+ });
}
/**
@@ -134,8 +147,7 @@
*/
TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
const native_handle_t* bufferHandle;
- ASSERT_NO_FATAL_FAILURE(bufferHandle =
- mGralloc->allocate(mDummyDescriptorInfo, true));
+ ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
}
@@ -144,16 +156,13 @@
*/
TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
const native_handle_t* clonedBufferHandle;
- ASSERT_NO_FATAL_FAILURE(
- clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+ ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
// A cloned handle is a raw handle. Check that we can import it multiple
// times.
const native_handle_t* importedBufferHandles[2];
- ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] =
- mGralloc->importBuffer(clonedBufferHandle));
- ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] =
- mGralloc->importBuffer(clonedBufferHandle));
+ ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] = mGralloc->importBuffer(clonedBufferHandle));
+ ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] = mGralloc->importBuffer(clonedBufferHandle));
ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
@@ -165,19 +174,20 @@
*/
TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
const native_handle_t* rawHandle;
- ASSERT_NO_FATAL_FAILURE(
- rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+ ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
native_handle_t* importedHandle = nullptr;
- mGralloc->getMapper()->importBuffer(
- rawHandle, [&](const auto& tmpError, const auto& buffer) {
- ASSERT_EQ(Error::NONE, tmpError);
- importedHandle = static_cast<native_handle_t*>(buffer);
- });
+ mGralloc->getMapper()->importBuffer(rawHandle, [&](const auto& tmpError, const auto& buffer) {
+ ASSERT_EQ(Error::NONE, tmpError);
+ importedHandle = static_cast<native_handle_t*>(buffer);
+ });
// free the imported handle with another mapper
std::unique_ptr<Gralloc> anotherGralloc;
- ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>());
+ ASSERT_NO_FATAL_FAILURE(
+ anotherGralloc = std::make_unique<Gralloc>(
+ GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
+ GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
ASSERT_EQ(Error::NONE, error);
@@ -203,15 +213,13 @@
*/
TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
native_handle_t* invalidHandle = nullptr;
- mGralloc->getMapper()->importBuffer(
- invalidHandle, [&](const auto& tmpError, const auto&) {
- EXPECT_EQ(Error::BAD_BUFFER, tmpError)
- << "importBuffer with nullptr did not fail with BAD_BUFFER";
- });
+ mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "importBuffer with nullptr did not fail with BAD_BUFFER";
+ });
invalidHandle = native_handle_create(0, 0);
- mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError,
- const auto&) {
+ mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "importBuffer with invalid handle did not fail with BAD_BUFFER";
});
@@ -224,8 +232,7 @@
TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
native_handle_t* invalidHandle = nullptr;
Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
- EXPECT_EQ(Error::BAD_BUFFER, error)
- << "freeBuffer with nullptr did not fail with BAD_BUFFER";
+ EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER";
invalidHandle = native_handle_create(0, 0);
error = mGralloc->getMapper()->freeBuffer(invalidHandle);
@@ -234,8 +241,7 @@
native_handle_delete(invalidHandle);
const native_handle_t* clonedBufferHandle;
- ASSERT_NO_FATAL_FAILURE(
- clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+ ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
error = mGralloc->getMapper()->freeBuffer(invalidHandle);
EXPECT_EQ(Error::BAD_BUFFER, error)
<< "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
@@ -251,16 +257,15 @@
const native_handle_t* bufferHandle;
uint32_t stride;
- ASSERT_NO_FATAL_FAILURE(bufferHandle =
- mGralloc->allocate(info, true, &stride));
+ ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
// lock buffer for writing
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
int fence = -1;
uint8_t* data;
- ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
- bufferHandle, info.usage, region, fence)));
+ ASSERT_NO_FATAL_FAILURE(
+ data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
// RGBA_8888
size_t strideInBytes = stride * 4;
@@ -274,8 +279,8 @@
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
// lock again for reading
- ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
- bufferHandle, info.usage, region, fence)));
+ ASSERT_NO_FATAL_FAILURE(
+ data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
for (uint32_t y = 0; y < info.height; y++) {
for (size_t i = 0; i < writeInBytes; i++) {
EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
@@ -299,16 +304,14 @@
const native_handle_t* bufferHandle;
uint32_t stride;
- ASSERT_NO_FATAL_FAILURE(bufferHandle =
- mGralloc->allocate(info, true, &stride));
+ ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
// lock buffer for writing
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
int fence = -1;
YCbCrLayout layout;
- ASSERT_NO_FATAL_FAILURE(
- layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+ ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
auto yData = static_cast<uint8_t*>(layout.y);
auto cbData = static_cast<uint8_t*>(layout.cb);
@@ -328,8 +331,7 @@
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
// lock again for reading
- ASSERT_NO_FATAL_FAILURE(
- layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+ ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
yData = static_cast<uint8_t*>(layout.y);
cbData = static_cast<uint8_t*>(layout.cb);
@@ -357,25 +359,21 @@
*/
TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
native_handle_t* invalidHandle = nullptr;
- mGralloc->getMapper()->unlock(
- invalidHandle, [&](const auto& tmpError, const auto&) {
- EXPECT_EQ(Error::BAD_BUFFER, tmpError)
- << "unlock with nullptr did not fail with BAD_BUFFER";
- });
+ mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "unlock with nullptr did not fail with BAD_BUFFER";
+ });
invalidHandle = native_handle_create(0, 0);
- mGralloc->getMapper()->unlock(
- invalidHandle, [&](const auto& tmpError, const auto&) {
- EXPECT_EQ(Error::BAD_BUFFER, tmpError)
- << "unlock with invalid handle did not fail with BAD_BUFFER";
- });
+ mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "unlock with invalid handle did not fail with BAD_BUFFER";
+ });
native_handle_delete(invalidHandle);
- ASSERT_NO_FATAL_FAILURE(invalidHandle =
- const_cast<native_handle_t*>(mGralloc->allocate(
- mDummyDescriptorInfo, false)));
- mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError,
- const auto&) {
+ ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
+ mGralloc->allocate(mDummyDescriptorInfo, false)));
+ mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with un-imported handle did not fail with BAD_BUFFER";
});
@@ -395,7 +393,7 @@
}
} // namespace
-} // namespace tests
+} // namespace vts
} // namespace V2_0
} // namespace mapper
} // namespace graphics
@@ -403,7 +401,7 @@
} // namespace android
int main(int argc, char** argv) {
- using android::hardware::graphics::mapper::V2_0::tests::GraphicsMapperHidlEnvironment;
+ using android::hardware::graphics::mapper::V2_0::vts::GraphicsMapperHidlEnvironment;
::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
diff --git a/graphics/mapper/2.1/default/Android.bp b/graphics/mapper/2.1/default/Android.bp
new file mode 100644
index 0000000..aa204a0
--- /dev/null
+++ b/graphics/mapper/2.1/default/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2016 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.
+
+cc_library_shared {
+ name: "android.hardware.graphics.mapper@2.0-impl-2.1",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["passthrough.cpp"],
+ header_libs: [
+ "android.hardware.graphics.mapper@2.1-passthrough",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+}
diff --git a/graphics/mapper/2.1/default/OWNERS b/graphics/mapper/2.1/default/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/mapper/2.1/default/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/mapper/2.1/default/passthrough.cpp b/graphics/mapper/2.1/default/passthrough.cpp
new file mode 100644
index 0000000..c7f0cf5
--- /dev/null
+++ b/graphics/mapper/2.1/default/passthrough.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-passthrough/2.1/GrallocLoader.h>
+
+using android::hardware::graphics::mapper::V2_1::IMapper;
+using android::hardware::graphics::mapper::V2_1::passthrough::GrallocLoader;
+
+extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
+ return GrallocLoader::load();
+}
diff --git a/graphics/mapper/2.1/utils/OWNERS b/graphics/mapper/2.1/utils/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/mapper/2.1/utils/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/mapper/2.1/utils/hal/Android.bp b/graphics/mapper/2.1/utils/hal/Android.bp
new file mode 100644
index 0000000..2a4cc6e
--- /dev/null
+++ b/graphics/mapper/2.1/utils/hal/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 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.
+
+cc_library_headers {
+ name: "android.hardware.graphics.mapper@2.1-hal",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ shared_libs: [
+ "android.hardware.graphics.mapper@2.1",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.mapper@2.1",
+ ],
+ header_libs: [
+ "android.hardware.graphics.mapper@2.0-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.mapper@2.0-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h
new file mode 100644
index 0000000..038f572
--- /dev/null
+++ b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Mapper.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-hal/2.0/Mapper.h>
+#include <mapper-hal/2.1/MapperHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace hal {
+
+namespace detail {
+
+// MapperImpl implements V2_*::IMapper on top of V2_*::hal::MapperHal
+template <typename Interface, typename Hal>
+class MapperImpl : public V2_0::hal::detail::MapperImpl<Interface, Hal> {
+ public:
+ // IMapper 2.1 interface
+ Return<Error> validateBufferSize(void* buffer,
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t stride) {
+ const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+ if (!bufferHandle) {
+ return Error::BAD_BUFFER;
+ }
+
+ return mHal->validateBufferSize(bufferHandle, descriptorInfo, stride);
+ }
+
+ Return<void> getTransportSize(void* buffer, IMapper::getTransportSize_cb hidl_cb) {
+ const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+ if (!bufferHandle) {
+ hidl_cb(Error::BAD_BUFFER, 0, 0);
+ return Void();
+ }
+
+ uint32_t numFds = 0;
+ uint32_t numInts = 0;
+ Error error = mHal->getTransportSize(bufferHandle, &numFds, &numInts);
+ hidl_cb(error, numFds, numInts);
+ return Void();
+ }
+
+ Return<void> createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ IMapper::createDescriptor_2_1_cb hidl_cb) override {
+ BufferDescriptor descriptor;
+ Error error = mHal->createDescriptor_2_1(descriptorInfo, &descriptor);
+ hidl_cb(error, descriptor);
+ return Void();
+ }
+
+ private:
+ using BaseType2_0 = V2_0::hal::detail::MapperImpl<Interface, Hal>;
+ using BaseType2_0::getImportedBuffer;
+ using BaseType2_0::mHal;
+};
+
+} // namespace detail
+
+using Mapper = detail::MapperImpl<IMapper, MapperHal>;
+
+} // namespace hal
+} // namespace V2_1
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/MapperHal.h b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/MapperHal.h
new file mode 100644
index 0000000..e488fab
--- /dev/null
+++ b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/MapperHal.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-hal/2.0/MapperHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace hal {
+
+using V2_0::BufferDescriptor;
+using V2_0::Error;
+
+class MapperHal : public V2_0::hal::MapperHal {
+ public:
+ virtual ~MapperHal() = default;
+
+ // superceded by createDescriptor_2_1
+ Error createDescriptor(const V2_0::IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) override {
+ return createDescriptor_2_1(
+ IMapper::BufferDescriptorInfo{
+ descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount,
+ static_cast<common::V1_1::PixelFormat>(descriptorInfo.format), descriptorInfo.usage,
+ },
+ outDescriptor);
+ }
+
+ // validate the buffer can be safely accessed with the specified
+ // descriptorInfo and stride
+ virtual Error validateBufferSize(const native_handle_t* bufferHandle,
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t stride) = 0;
+
+ // get the transport size of a buffer handle. It can be smaller than or
+ // equal to the size of the buffer handle.
+ virtual Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+ uint32_t* outNumInts) = 0;
+
+ // create a BufferDescriptor
+ virtual Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) = 0;
+};
+
+} // namespace hal
+} // namespace V2_1
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.1/utils/passthrough/Android.bp b/graphics/mapper/2.1/utils/passthrough/Android.bp
new file mode 100644
index 0000000..6946a53
--- /dev/null
+++ b/graphics/mapper/2.1/utils/passthrough/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2016 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.
+
+cc_library_headers {
+ name: "android.hardware.graphics.mapper@2.1-passthrough",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ shared_libs: [
+ "android.hardware.graphics.mapper@2.1",
+ "libhardware",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.mapper@2.1",
+ "libhardware",
+ ],
+ header_libs: [
+ "android.hardware.graphics.mapper@2.0-passthrough",
+ "android.hardware.graphics.mapper@2.1-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.mapper@2.0-passthrough",
+ "android.hardware.graphics.mapper@2.1-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
new file mode 100644
index 0000000..b704fdb
--- /dev/null
+++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#pragma once
+
+#include <mapper-hal/2.1/MapperHal.h>
+#include <mapper-passthrough/2.0/Gralloc0Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace passthrough {
+
+namespace detail {
+
+using V2_0::BufferDescriptor;
+using V2_0::Error;
+
+// Gralloc0HalImpl implements V2_*::hal::MapperHal on top of gralloc0
+template <typename Hal>
+class Gralloc0HalImpl : public V2_0::passthrough::detail::Gralloc0HalImpl<Hal> {
+ public:
+ Error validateBufferSize(const native_handle_t* /*bufferHandle*/,
+ const IMapper::BufferDescriptorInfo& /*descriptorInfo*/,
+ uint32_t /*stride*/) override {
+ // need a gralloc0 extension to really validate
+ return Error::NONE;
+ }
+
+ Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+ uint32_t* outNumInts) override {
+ // need a gralloc0 extension to get the transport size
+ *outNumFds = bufferHandle->numFds;
+ *outNumInts = bufferHandle->numInts;
+ return Error::NONE;
+ }
+
+ Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) override {
+ return createDescriptor(
+ V2_0::IMapper::BufferDescriptorInfo{
+ descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount,
+ static_cast<common::V1_0::PixelFormat>(descriptorInfo.format), descriptorInfo.usage,
+ },
+ outDescriptor);
+ }
+
+ private:
+ using BaseType2_0 = V2_0::passthrough::detail::Gralloc0HalImpl<Hal>;
+ using BaseType2_0::createDescriptor;
+};
+
+} // namespace detail
+
+using Gralloc0Hal = detail::Gralloc0HalImpl<hal::MapperHal>;
+
+} // namespace passthrough
+} // namespace V2_1
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc1Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc1Hal.h
new file mode 100644
index 0000000..8b695e4
--- /dev/null
+++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc1Hal.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#pragma once
+
+#include <hardware/gralloc1.h>
+#include <mapper-hal/2.1/MapperHal.h>
+#include <mapper-passthrough/2.0/Gralloc1Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace passthrough {
+
+using V2_0::BufferDescriptor;
+using V2_0::Error;
+
+namespace detail {
+
+// Gralloc1HalImpl implements V2_*::hal::MapperHal on top of gralloc1
+template <typename Hal>
+class Gralloc1HalImpl : public V2_0::passthrough::detail::Gralloc1HalImpl<Hal> {
+ public:
+ Error validateBufferSize(const native_handle_t* bufferHandle,
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t stride) override {
+ uint32_t bufferWidth;
+ uint32_t bufferHeight;
+ uint32_t bufferLayerCount;
+ int32_t bufferFormat;
+ uint64_t bufferProducerUsage;
+ uint64_t bufferConsumerUsage;
+ uint32_t bufferStride;
+
+ int32_t error = mDispatch.getDimensions(mDevice, bufferHandle, &bufferWidth, &bufferHeight);
+ if (error != GRALLOC1_ERROR_NONE) {
+ return toError(error);
+ }
+ error = mDispatch.getLayerCount(mDevice, bufferHandle, &bufferLayerCount);
+ if (error != GRALLOC1_ERROR_NONE) {
+ return toError(error);
+ }
+ error = mDispatch.getFormat(mDevice, bufferHandle, &bufferFormat);
+ if (error != GRALLOC1_ERROR_NONE) {
+ return toError(error);
+ }
+ error = mDispatch.getProducerUsage(mDevice, bufferHandle, &bufferProducerUsage);
+ if (error != GRALLOC1_ERROR_NONE) {
+ return toError(error);
+ }
+ error = mDispatch.getConsumerUsage(mDevice, bufferHandle, &bufferConsumerUsage);
+ if (error != GRALLOC1_ERROR_NONE) {
+ return toError(error);
+ }
+ error = mDispatch.getStride(mDevice, bufferHandle, &bufferStride);
+ if (error != GRALLOC1_ERROR_NONE) {
+ return toError(error);
+ }
+
+ // TODO format? usage? width > stride?
+ // need a gralloc1 extension to really validate
+ (void)bufferFormat;
+ (void)bufferProducerUsage;
+ (void)bufferConsumerUsage;
+
+ if (descriptorInfo.width > bufferWidth || descriptorInfo.height > bufferHeight ||
+ descriptorInfo.layerCount > bufferLayerCount || stride > bufferStride) {
+ return Error::BAD_VALUE;
+ }
+
+ return Error::NONE;
+ }
+
+ Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+ uint32_t* outNumInts) override {
+ // need a gralloc1 extension to get the transport size
+ *outNumFds = bufferHandle->numFds;
+ *outNumInts = bufferHandle->numInts;
+ return Error::NONE;
+ }
+
+ Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) override {
+ return createDescriptor(
+ V2_0::IMapper::BufferDescriptorInfo{
+ descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount,
+ static_cast<common::V1_0::PixelFormat>(descriptorInfo.format), descriptorInfo.usage,
+ },
+ outDescriptor);
+ }
+
+ protected:
+ bool initDispatch() override {
+ if (!BaseType2_0::initDispatch()) {
+ return false;
+ }
+
+ if (!initDispatch(GRALLOC1_FUNCTION_GET_DIMENSIONS, &mDispatch.getDimensions) ||
+ !initDispatch(GRALLOC1_FUNCTION_GET_LAYER_COUNT, &mDispatch.getLayerCount) ||
+ !initDispatch(GRALLOC1_FUNCTION_GET_FORMAT, &mDispatch.getFormat) ||
+ !initDispatch(GRALLOC1_FUNCTION_GET_PRODUCER_USAGE, &mDispatch.getProducerUsage) ||
+ !initDispatch(GRALLOC1_FUNCTION_GET_CONSUMER_USAGE, &mDispatch.getConsumerUsage) ||
+ !initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ struct {
+ GRALLOC1_PFN_GET_DIMENSIONS getDimensions;
+ GRALLOC1_PFN_GET_LAYER_COUNT getLayerCount;
+ GRALLOC1_PFN_GET_FORMAT getFormat;
+ GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage;
+ GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage;
+ GRALLOC1_PFN_GET_STRIDE getStride;
+ } mDispatch = {};
+
+ private:
+ using BaseType2_0 = V2_0::passthrough::detail::Gralloc1HalImpl<Hal>;
+ using BaseType2_0::createDescriptor;
+ using BaseType2_0::initDispatch;
+ using BaseType2_0::mDevice;
+ using BaseType2_0::toError;
+};
+
+} // namespace detail
+
+using Gralloc1Hal = detail::Gralloc1HalImpl<hal::MapperHal>;
+
+} // namespace passthrough
+} // namespace V2_1
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/GrallocLoader.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/GrallocLoader.h
new file mode 100644
index 0000000..f2c67db
--- /dev/null
+++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/GrallocLoader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <log/log.h>
+#include <mapper-hal/2.1/Mapper.h>
+#include <mapper-hal/2.1/MapperHal.h>
+#include <mapper-passthrough/2.0/GrallocLoader.h>
+#include <mapper-passthrough/2.1/Gralloc0Hal.h>
+#include <mapper-passthrough/2.1/Gralloc1Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace passthrough {
+
+class GrallocLoader : public V2_0::passthrough::GrallocLoader {
+ public:
+ static IMapper* load() {
+ const hw_module_t* module = loadModule();
+ if (!module) {
+ return nullptr;
+ }
+ auto hal = createHal(module);
+ if (!hal) {
+ return nullptr;
+ }
+ return createMapper(std::move(hal));
+ }
+
+ // create a MapperHal instance
+ static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) {
+ int major = getModuleMajorApiVersion(module);
+ switch (major) {
+ case 1: {
+ auto hal = std::make_unique<Gralloc1Hal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+ case 0: {
+ auto hal = std::make_unique<Gralloc0Hal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+ default:
+ ALOGE("unknown gralloc module major version %d", major);
+ return nullptr;
+ }
+ }
+
+ // create an IAllocator instance
+ static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) {
+ auto mapper = std::make_unique<V2_0::passthrough::GrallocMapper<hal::Mapper>>();
+ return mapper->init(std::move(hal)) ? mapper.release() : nullptr;
+ }
+};
+
+} // namespace passthrough
+} // namespace V2_1
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.1/utils/vts/Android.bp b/graphics/mapper/2.1/utils/vts/Android.bp
new file mode 100644
index 0000000..ca02aad
--- /dev/null
+++ b/graphics/mapper/2.1/utils/vts/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2016 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.
+//
+
+cc_library_static {
+ name: "android.hardware.graphics.mapper@2.1-vts",
+ defaults: ["hidl_defaults"],
+ srcs: ["MapperVts.cpp"],
+ cflags: [
+ "-O0",
+ "-g",
+ ],
+ static_libs: [
+ "VtsHalHidlTargetTestBase",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.0-vts",
+ "android.hardware.graphics.mapper@2.1",
+ ],
+ export_static_lib_headers: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.0-vts",
+ "android.hardware.graphics.mapper@2.1",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.1/utils/vts/MapperVts.cpp b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
new file mode 100644
index 0000000..0aaa926
--- /dev/null
+++ b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <mapper-vts/2.1/MapperVts.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace vts {
+
+using V2_0::Error;
+
+// abuse VTS to check binary compatibility between BufferDescriptorInfos
+using OldBufferDescriptorInfo =
+ android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo;
+static_assert(sizeof(OldBufferDescriptorInfo) == sizeof(IMapper::BufferDescriptorInfo) &&
+ offsetof(OldBufferDescriptorInfo, width) ==
+ offsetof(IMapper::BufferDescriptorInfo, width) &&
+ offsetof(OldBufferDescriptorInfo, height) ==
+ offsetof(IMapper::BufferDescriptorInfo, height) &&
+ offsetof(OldBufferDescriptorInfo, layerCount) ==
+ offsetof(IMapper::BufferDescriptorInfo, layerCount) &&
+ offsetof(OldBufferDescriptorInfo, format) ==
+ offsetof(IMapper::BufferDescriptorInfo, format) &&
+ offsetof(OldBufferDescriptorInfo, usage) ==
+ offsetof(IMapper::BufferDescriptorInfo, usage),
+ "");
+
+Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName)
+ : V2_0::vts::Gralloc(allocatorServiceName, mapperServiceName) {
+ if (::testing::Test::HasFatalFailure()) {
+ return;
+ }
+ init();
+}
+
+void Gralloc::init() {
+ mMapperV2_1 = IMapper::castFrom(V2_0::vts::Gralloc::getMapper());
+ ASSERT_NE(nullptr, mMapperV2_1.get()) << "failed to get mapper 2.1 service";
+}
+
+sp<IMapper> Gralloc::getMapper() const {
+ return mMapperV2_1;
+}
+
+bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle,
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t stride) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ Error error = mMapperV2_1->validateBufferSize(buffer, descriptorInfo, stride);
+ return error == Error::NONE;
+}
+
+void Gralloc::getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+ uint32_t* outNumInts) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ *outNumFds = 0;
+ *outNumInts = 0;
+ mMapperV2_1->getTransportSize(
+ buffer, [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size";
+ ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds;
+ ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts;
+
+ *outNumFds = tmpNumFds;
+ *outNumInts = tmpNumInts;
+ });
+}
+
+BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
+ BufferDescriptor descriptor;
+ mMapperV2_1->createDescriptor_2_1(
+ descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
+ descriptor = tmpDescriptor;
+ });
+
+ return descriptor;
+}
+
+const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ bool import, uint32_t* outStride) {
+ BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+ if (::testing::Test::HasFatalFailure()) {
+ return nullptr;
+ }
+
+ auto buffers = V2_0::vts::Gralloc::allocate(descriptor, 1, import, outStride);
+ if (::testing::Test::HasFatalFailure()) {
+ return nullptr;
+ }
+
+ return buffers[0];
+}
+
+} // namespace vts
+} // namespace V2_1
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
new file mode 100644
index 0000000..b7fa751
--- /dev/null
+++ b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-vts/2.0/MapperVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace vts {
+
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using V2_0::BufferDescriptor;
+
+// A wrapper to IAllocator and IMapper.
+class Gralloc : public V2_0::vts::Gralloc {
+ public:
+ Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName);
+
+ sp<IMapper> getMapper() const;
+
+ bool validateBufferSize(const native_handle_t* bufferHandle,
+ const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride);
+ void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+ uint32_t* outNumInts);
+
+ BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
+
+ const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ bool import = true, uint32_t* outStride = nullptr);
+
+ protected:
+ void init();
+
+ sp<IMapper> mMapperV2_1;
+};
+
+} // namespace vts
+} // namespace V2_1
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.1/vts/functional/Android.bp b/graphics/mapper/2.1/vts/functional/Android.bp
index 578d298..ac67af8 100644
--- a/graphics/mapper/2.1/vts/functional/Android.bp
+++ b/graphics/mapper/2.1/vts/functional/Android.bp
@@ -18,15 +18,12 @@
name: "VtsHalGraphicsMapperV2_1TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalGraphicsMapperV2_1TargetTest.cpp"],
- shared_libs: [
- "libsync",
- ],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
- "libVtsHalGraphicsMapperTestUtils",
- "libnativehelper",
+ "android.hardware.graphics.mapper@2.0-vts",
+ "android.hardware.graphics.mapper@2.1-vts",
],
}
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
index 88b96ae..5e7cf93 100644
--- a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -19,115 +19,43 @@
#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hardware/graphics/mapper/2.1/IMapper.h>
-#include <sync/sync.h>
-#include "VtsHalGraphicsMapperTestUtils.h"
+#include <mapper-vts/2.1/MapperVts.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_1 {
-namespace tests {
+namespace vts {
namespace {
-using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using android::hardware::graphics::mapper::V2_0::Error;
-
+using android::hardware::graphics::allocator::V2_0::IAllocator;
using android::hardware::graphics::common::V1_1::BufferUsage;
using android::hardware::graphics::common::V1_1::PixelFormat;
+using V2_0::Error;
-// abuse VTS to check binary compatibility between BufferDescriptorInfos
-using OldBufferDescriptorInfo =
- android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo;
-static_assert(sizeof(OldBufferDescriptorInfo) == sizeof(IMapper::BufferDescriptorInfo) &&
- offsetof(OldBufferDescriptorInfo, width) ==
- offsetof(IMapper::BufferDescriptorInfo, width) &&
- offsetof(OldBufferDescriptorInfo, height) ==
- offsetof(IMapper::BufferDescriptorInfo, height) &&
- offsetof(OldBufferDescriptorInfo, layerCount) ==
- offsetof(IMapper::BufferDescriptorInfo, layerCount) &&
- offsetof(OldBufferDescriptorInfo, format) ==
- offsetof(IMapper::BufferDescriptorInfo, format) &&
- offsetof(OldBufferDescriptorInfo, usage) ==
- offsetof(IMapper::BufferDescriptorInfo, usage),
- "");
-
-class Gralloc : public V2_0::tests::Gralloc {
+// Test environment for graphics.mapper.
+class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
public:
- Gralloc() : V2_0::tests::Gralloc() {
- if (::testing::Test::HasFatalFailure()) {
- return;
- }
-
- init();
+ // get the test environment singleton
+ static GraphicsMapperHidlEnvironment* Instance() {
+ static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
+ return instance;
}
- sp<IMapper> getMapper() const { return mMapper; }
-
- bool validateBufferSize(const native_handle_t* bufferHandle,
- const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
- Error error = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
- return error == Error::NONE;
+ virtual void registerTestServices() override {
+ registerTestService<IAllocator>();
+ registerTestService<IMapper>();
}
-
- void getTransportSize(const native_handle_t* bufferHandle, uint32_t* numFds,
- uint32_t* numInts) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
- *numFds = 0;
- *numInts = 0;
- mMapper->getTransportSize(buffer, [&](const auto& tmpError, const auto& tmpNumFds,
- const auto& tmpNumInts) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size";
- ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds;
- ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts;
-
- *numFds = tmpNumFds;
- *numInts = tmpNumInts;
- });
- }
-
- BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
- BufferDescriptor descriptor;
- mMapper->createDescriptor_2_1(
- descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
- descriptor = tmpDescriptor;
- });
-
- return descriptor;
- }
-
- const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
- bool import, uint32_t* outStride = nullptr) {
- BufferDescriptor descriptor = createDescriptor(descriptorInfo);
- if (::testing::Test::HasFatalFailure()) {
- return nullptr;
- }
-
- auto buffers = V2_0::tests::Gralloc::allocate(descriptor, 1, import, outStride);
- if (::testing::Test::HasFatalFailure()) {
- return nullptr;
- }
-
- return buffers[0];
- }
-
- private:
- void init() {
- mMapper = IMapper::castFrom(V2_0::tests::Gralloc::getMapper());
- ASSERT_NE(nullptr, mMapper.get()) << "failed to find IMapper 2.1";
- }
-
- sp<IMapper> mMapper;
};
class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
protected:
void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+ ASSERT_NO_FATAL_FAILURE(
+ mGralloc = std::make_unique<Gralloc>(
+ GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
+ GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
mDummyDescriptorInfo.width = 64;
mDummyDescriptorInfo.height = 64;
@@ -291,7 +219,7 @@
}
} // namespace
-} // namespace tests
+} // namespace vts
} // namespace V2_1
} // namespace mapper
} // namespace graphics
@@ -299,7 +227,7 @@
} // namespace android
int main(int argc, char** argv) {
- using android::hardware::graphics::mapper::V2_0::tests::GraphicsMapperHidlEnvironment;
+ using android::hardware::graphics::mapper::V2_1::vts::GraphicsMapperHidlEnvironment;
::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
diff --git a/health/2.0/README b/health/2.0/README
index a0a5f08..49b2b1e 100644
--- a/health/2.0/README
+++ b/health/2.0/README
@@ -96,4 +96,4 @@
# device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
# Add device specific permissions to hal_health_default domain, especially
-# if Step 6.2 or Step 7.2 is done.
+# if Step 6.1 or Step 7.2 is done.
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
new file mode 100644
index 0000000..986da8a
--- /dev/null
+++ b/media/bufferpool/1.0/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.media.bufferpool@1.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IAccessor.hal",
+ "IClientManager.hal",
+ "IConnection.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "Buffer",
+ "BufferStatus",
+ "BufferStatusMessage",
+ "ResultStatus",
+ ],
+ gen_java: false,
+}
+
diff --git a/media/bufferpool/1.0/IAccessor.hal b/media/bufferpool/1.0/IAccessor.hal
new file mode 100644
index 0000000..5b5aec0
--- /dev/null
+++ b/media/bufferpool/1.0/IAccessor.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.media.bufferpool@1.0;
+
+import IConnection;
+/**
+ * IAccessor creates IConnection which is used from IClientManager in order to
+ * use functionality of the specified buffer pool.
+ */
+interface IAccessor {
+
+ /**
+ * Registers a new client and creates IConnection to the buffer pool for
+ * the client. IConnection and FMQ are used by IClientManager in order to
+ * communicate with the buffer pool. Via FMQ IClientManager sends
+ * BufferStatusMesage(s) to the buffer pool.
+ *
+ * FMQ is used to send buffer ownership status changes to a buffer pool
+ * from a buffer pool client. A buffer pool synchronizes FMQ messages when
+ * there is a hidl request from the clients. Every client has its own
+ * connection and FMQ to communicate with the buffer pool. So sending an
+ * FMQ message on behalf of other clients is not possible.
+ *
+ * FMQ messages are sent when a buffer is acquired or released. Also, FMQ
+ * messages are sent when a buffer is transferred from a client to another
+ * client. FMQ has its own ID from a buffer pool. A client is specified
+ * with the ID.
+ *
+ * To transfer a buffer, a sender must send an FMQ message. The message
+ * must include a receiver's ID and a transaction ID. A receiver must send
+ * the transaction ID to fetch a buffer from a buffer pool. Since the
+ * sender already registered the receiver via an FMQ message, The buffer
+ * pool must verify the receiver with the transaction ID. In order to
+ * prevent faking a receiver, a connection to a buffer pool from client is
+ * made and kept private. Also part of transaction ID is a sender ID in
+ * order to prevent fake transactions from other clients. This must be
+ * verified with an FMQ message from a buffer pool.
+ *
+ * @return status The status of the call.
+ * OK - A connection is made successfully.
+ * NO_MEMORY - Memory allocation failure occurred.
+ * ALREADY_EXISTS - A connection was already made.
+ * CRITICAL_ERROR - Other errors.
+ * @return connection The IConnection have interfaces
+ * to get shared buffers from the buffer pool.
+ * @return connectionId Id of IConnection. The Id identifies
+ * sender and receiver in FMQ messages during buffer transfer.
+ * @return mqDesc FMQ descriptor. The descriptor can be used to
+ * send/receive FMQ messages.
+ */
+ connect()
+ generates (ResultStatus status, IConnection connection,
+ int64_t connectionId, fmq_sync<BufferStatusMessage> mqDesc);
+};
diff --git a/media/bufferpool/1.0/IClientManager.hal b/media/bufferpool/1.0/IClientManager.hal
new file mode 100644
index 0000000..e1e8f95
--- /dev/null
+++ b/media/bufferpool/1.0/IClientManager.hal
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.media.bufferpool@1.0;
+
+import IAccessor;
+/**
+ * IClientManager manages IConnection(s) inside a process. A locally
+ * created IConnection represents a communication node(receiver) with the
+ * specified buffer pool(IAccessor).
+ * IConnection(s) are not exposed to other processes(IClientManager).
+ * IClientManager instance must be unique within a process.
+ */
+interface IClientManager {
+
+ /**
+ * Sets up a buffer receiving communication node for the specified
+ * buffer pool. A manager must create a IConnection to the buffer
+ * pool if it does not already have a connection.
+ *
+ * @param bufferPool a buffer pool which is specified with the IAccessor.
+ * The specified buffer pool is the owner of received buffers.
+ * @return status The status of the call.
+ * OK - A sender was set successfully.
+ * NO_MEMORY - Memory allocation failure occurred.
+ * ALREADY_EXISTS - A sender was registered already.
+ * CRITICAL_ERROR - Other errors.
+ * @return connectionId the Id of the communication node to the buffer pool.
+ * This id is used in FMQ to notify IAccessor that a buffer has been
+ * sent to that connection during transfers.
+ */
+ registerSender(IAccessor bufferPool) generates
+ (ResultStatus status, int64_t connectionId);
+};
diff --git a/media/bufferpool/1.0/IConnection.hal b/media/bufferpool/1.0/IConnection.hal
new file mode 100644
index 0000000..e284db2
--- /dev/null
+++ b/media/bufferpool/1.0/IConnection.hal
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.media.bufferpool@1.0;
+
+/**
+ * A connection to a buffer pool which handles requests from a buffer pool
+ * client. The connection must be made in order to receive buffers from
+ * other buffer pool clients.
+ */
+interface IConnection {
+
+ /**
+ * Retrieves a buffer using bufferId. The method must be called from
+ * receiving side of buffer during transferring only when the specified
+ * buffer is neither cached nor used. This fails if the specified
+ * transaction is not valid.
+ *
+ * @param transactionId Unique transaction id for buffer transferring.
+ * @param bufferId Id of the buffer to be fetched.
+ * @return status The status of the call.
+ * OK - A buffer was fetched successfully.
+ * NO_MEMORY - Memory allocation failure occurred.
+ * NOT_FOUND - A buffer was not found due to invalidation.
+ * CRITICAL_ERROR - Other errors.
+ * @return buffer The actual buffer which is specified with bufferId.
+ */
+ fetch(uint64_t transactionId, uint32_t bufferId) generates
+ (ResultStatus status, Buffer buffer);
+};
diff --git a/media/bufferpool/1.0/README.md b/media/bufferpool/1.0/README.md
new file mode 100644
index 0000000..ed985d8
--- /dev/null
+++ b/media/bufferpool/1.0/README.md
@@ -0,0 +1,54 @@
+1. Overview
+
+A buffer pool enables processes to transfer buffers asynchronously.
+Without a buffer pool, a process calls a synchronous method of the other
+process and waits until the call finishes transferring a buffer. This adds
+unwanted latency due to context switching. With help from a buffer pool, a
+process can pass buffers asynchronously and reduce context switching latency.
+
+Passing an interface and a handle adds extra latency also. To mitigate the
+latency, passing IDs with local cache is used. For security concerns about
+rogue clients, FMQ is used to communicate between a buffer pool and a client
+process. FMQ is used to send buffer ownership change status from a client
+process to a buffer pool. Except FMQ, a buffer pool does not use any shared
+memory.
+
+2. FMQ
+
+FMQ is used to send buffer ownership status changes to a buffer pool from a
+buffer pool client. A buffer pool synchronizes FMQ messages when there is a
+hidl request from the clients. Every client has its own connection and FMQ
+to communicate with the buffer pool. So sending an FMQ message on behalf of
+other clients is not possible.
+
+FMQ messages are sent when a buffer is acquired or released. Also, FMQ messages
+are sent when a buffer is transferred from a client to another client. FMQ has
+its own ID from a buffer pool. A client is specified with the ID.
+
+To transfer a buffer, a sender must send an FMQ message. The message must
+include a receiver's ID and a transaction ID. A receiver must send the
+transaction ID to fetch a buffer from a buffer pool. Since the sender already
+registered the receiver via an FMQ message, The buffer pool must verify the
+receiver with the transaction ID. In order to prevent faking a receiver, a
+connection to a buffer pool from client is made and kept privately. Also part of
+transaction ID is a sender ID in order to prevent fake transactions from other
+clients. This must be verified with an FMQ message from a buffer pool.
+
+FMQ messages are defined in BufferStatus and BufferStatusMessage of 'types.hal'.
+
+3. Interfaces
+
+IConnection
+A connection to a buffer pool from a buffer pool client. The connection
+provides the functionalities to share buffers between buffer pool clients.
+The connection must be unique for each client.
+
+IAccessor
+An accessor to a buffer pool which makes a connection to the buffer pool.
+IAccesssor#connect creates an IConnection.
+
+IClientManager
+A manager of buffer pool clients and clients' connections to buffer pools. It
+sets up a process to be a receiver of buffers from a buffer pool. The manager
+is unique in a process.
+
diff --git a/media/bufferpool/1.0/types.hal b/media/bufferpool/1.0/types.hal
new file mode 100644
index 0000000..d8ab597
--- /dev/null
+++ b/media/bufferpool/1.0/types.hal
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.media.bufferpool@1.0;
+
+enum ResultStatus : int32_t {
+ OK = 0,
+
+ NO_MEMORY = 1,
+ ALREADY_EXISTS = 2,
+ NOT_FOUND = 3,
+ CRITICAL_ERROR = 4,
+};
+
+/**
+ * Generic buffer for fast recycling for media/stagefright.
+ *
+ * During media pipeline buffer references are created, shared and
+ * destroyed frequently. The underlying buffers are allocated on demand
+ * by a buffer pool, and are recycled to the buffer pool when they are
+ * no longer referenced by the clients.
+ *
+ * E.g. ion or gralloc buffer
+ */
+struct Buffer {
+ uint32_t id;
+ handle buffer;
+};
+
+/**
+ * Buffer ownership status for the specified client.
+ * Buffer transfer status for the specified buffer transafer transaction.
+ * BufferStatus is posted along with BufferStatusMessage from a client to
+ * the buffer pool for synchronization after status change.
+ */
+enum BufferStatus : int32_t {
+ /** No longer used by the specified client. */
+ NOT_USED = 0,
+ /** Buffer is acquired by the specified client. */
+ USED = 1,
+ /** Buffer is sent by the specified client. */
+ TRANSFER_TO = 2,
+ /** Buffer transfer is acked by the receiver client. */
+ TRANSFER_FROM = 3,
+ /** Buffer transfer is timed out by receiver client. */
+ TRANSFER_TIMEOUT = 4,
+ /** Buffer transfer is not acked by the receiver. */
+ TRANSFER_LOST = 5,
+ /** Buffer fetch request from the client. */
+ TRANSFER_FETCH = 6,
+ /** Buffer transaction succeeded. */
+ TRANSFER_OK = 7,
+ /** Buffer transaction failure. */
+ TRANSFER_ERROR = 8,
+};
+
+/**
+ * Buffer ownership status change message. This message is
+ * sent via fmq to the buffer pool from client processes.
+ */
+struct BufferStatusMessage {
+ /**
+ * Transaction Id = (SenderId : sender local transaction Id)
+ * Transaction Id is created from sender and posted via fmq within
+ * TRANSFER_TO message.
+ */
+ uint64_t transactionId;
+ uint32_t bufferId;
+ BufferStatus newStatus;
+ /** Used by the buffer pool. not by client. */
+ int64_t connectionId;
+ /** Valid only when TRANSFER_TO is posted. */
+ int64_t targetConnectionId;
+ /**
+ * Used by the buffer pool, not by client.
+ * Monotonic timestamp in Us since fixed point in time as decided
+ * by the sender of the message
+ */
+ int64_t timestampUs;
+};
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
new file mode 100644
index 0000000..9365d4e
--- /dev/null
+++ b/neuralnetworks/1.1/Android.bp
@@ -0,0 +1,24 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.neuralnetworks@1.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IDevice.hal",
+ ],
+ interfaces: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "Model",
+ "Operation",
+ "OperationType",
+ ],
+ gen_java: false,
+}
+
diff --git a/neuralnetworks/1.1/IDevice.hal b/neuralnetworks/1.1/IDevice.hal
new file mode 100644
index 0000000..9d3fc31
--- /dev/null
+++ b/neuralnetworks/1.1/IDevice.hal
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.neuralnetworks@1.1;
+
+import @1.0::ErrorStatus;
+import @1.0::IDevice;
+import @1.0::IPreparedModelCallback;
+
+/**
+ * This interface represents a device driver.
+ */
+interface IDevice extends @1.0::IDevice {
+ /**
+ * Gets the supported operations in a model.
+ *
+ * getSupportedSubgraph indicates which operations of a model are fully
+ * supported by the vendor driver. If an operation may not be supported for
+ * any reason, getSupportedOperations must return false for that operation.
+ *
+ * @param model A model whose operations--and their corresponding
+ * operands--are to be verified by the driver.
+ * @return status Error status of the call, must be:
+ * - NONE if successful
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if provided model is invalid
+ * @return supportedOperations A list of supported operations, where true
+ * indicates the operation is supported and
+ * false indicates the operation is not
+ * supported. The index of "supported"
+ * corresponds with the index of the operation
+ * it is describing.
+ */
+ getSupportedOperations_1_1(Model model)
+ generates (ErrorStatus status, vec<bool> supportedOperations);
+
+ /**
+ * Creates a prepared model for execution.
+ *
+ * prepareModel is used to make any necessary transformations or alternative
+ * representations to a model for execution, possiblly including
+ * transformations on the constant data, optimization on the model's graph,
+ * or compilation into the device's native binary format. The model itself
+ * is not changed.
+ *
+ * The model is prepared asynchronously with respect to the caller. The
+ * prepareModel function must verify the inputs to the prepareModel function
+ * are correct. If there is an error, prepareModel must immediately invoke
+ * the callback with the appropriate ErrorStatus value and nullptr for the
+ * IPreparedModel, then return with the same ErrorStatus. If the inputs to
+ * the prepareModel function are valid and there is no error, prepareModel
+ * must launch an asynchronous task to prepare the model in the background,
+ * and immediately return from prepareModel with ErrorStatus::NONE. If the
+ * asynchronous task fails to launch, prepareModel must immediately invoke
+ * the callback with ErrorStatus::GENERAL_FAILURE and nullptr for the
+ * IPreparedModel, then return with ErrorStatus::GENERAL_FAILURE.
+ *
+ * When the asynchronous task has finished preparing the model, it must
+ * immediately invoke the callback function provided as an input to
+ * prepareModel. If the model was prepared successfully, the callback object
+ * must be invoked with an error status of ErrorStatus::NONE and the
+ * produced IPreparedModel object. If an error occurred preparing the model,
+ * the callback object must be invoked with the appropriate ErrorStatus
+ * value and nullptr for the IPreparedModel.
+ *
+ * The only information that may be unknown to the model at this stage is
+ * the shape of the tensors, which may only be known at execution time. As
+ * such, some driver services may return partially prepared models, where
+ * the prepared model can only be finished when it is paired with a set of
+ * inputs to the model. Note that the same prepared model object can be
+ * used with different shapes of inputs on different (possibly concurrent)
+ * executions.
+ *
+ * Multiple threads can call prepareModel on the same model concurrently.
+ *
+ * @param model The model to be prepared for execution.
+ * @param callback A callback object used to return the error status of
+ * preparing the model for execution and the prepared model
+ * if successful, nullptr otherwise. The callback object's
+ * notify function must be called exactly once, even if the
+ * model could not be prepared.
+ * @return status Error status of launching a task which prepares the model
+ * in the background; must be:
+ * - NONE if preparation task is successfully launched
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is
+ * invalid
+ */
+ prepareModel_1_1(Model model, IPreparedModelCallback callback)
+ generates (ErrorStatus status);
+};
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
new file mode 100644
index 0000000..18863d3
--- /dev/null
+++ b/neuralnetworks/1.1/types.hal
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.neuralnetworks@1.1;
+
+import @1.0::Operand;
+import @1.0::OperationType;
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : @1.0::OperationType {
+ /**
+ * BatchToSpace for N-D tensors.
+ *
+ * This operation reshapes the "batch" dimension 0 into M + 1 dimensions of shape
+ * block_shape + [batch], interleaves these blocks back into the grid defined by the
+ * spatial dimensions [1, ..., M], to obtain a result with the same rank as the input.
+ * The spatial dimensions of this intermediate result are then optionally cropped
+ * according to the amount to crop to produce the output.
+ * This is the reverse of SpaceToBatch.
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: An n-D tensor, specifying the input.
+ * 1: A 1-D Tensor of type TENSOR_INT32, the block sizes for each spatial dimension of the
+ * input tensor. All values must be >= 1.
+ * 2: A 1-D Tensor of type TENSOR_INT32, the amount to crop for each spatial diemension of the
+ * input tensor. All values must be >= 0.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0.
+ */
+ BATCH_TO_SPACE_ND = 29,
+
+ /**
+ * Divides the second tensor from the first tensor, element-wise.
+ *
+ * Takes two input tensors of identical OperandType and compatible dimensions. The output
+ * is the result of dividing the first input tensor by the second, optionally
+ * modified by an activation function.
+ *
+ * Two dimensions are compatible when:
+ * 1. they are equal, or
+ * 2. one of them is 1
+ *
+ * The size of the output is the maximum size along each dimension of the input operands.
+ * It starts with the trailing dimensions, and works its way forward.
+ *
+ * Example:
+ * input1.dimension = {4, 1, 2}
+ * input2.dimension = {5, 4, 3, 1}
+ * output.dimension = {5, 4, 3, 2}
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: An n-D tensor, specifying the first input.
+ * 1: A tensor of the same type, and compatible dimensions as input0.
+ * 2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+ * Specifies the activation to invoke on the result of each addition.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0.
+ */
+ DIV = 30,
+
+ /**
+ * Computes the mean of elements across dimensions of a tensor.
+ *
+ * Reduces input tensor along the dimensions given in axis. Unless keep_dims is true,
+ * the rank of the tensor is reduced by 1 for each entry in axis. If keep_dims is
+ * true, the reduced dimensions are retained with length 1.
+ *
+ * If axis has no entries, all dimensions are reduced, and a tensor with a single
+ * element is returned.
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: A tensor, specifying the input.
+ * 1: A 1-D Tensor of type TENSOR_INT32. The dimensions to reduce. If None (the default),
+ * reduces all dimensions. Must be in the range [-rank(input_tensor), rank(input_tensor)).
+ * 2: An INT32 value, keep_dims. If positive, retains reduced dimensions with length 1.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0.
+ */
+ MEAN = 31,
+
+ /**
+ * Pads a tensor.
+ *
+ * This operation pads a tensor according to the specified paddings.
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: An n-D tensor, specifying the input.
+ * 1: A 2-D Tensor of type TENSOR_INT32. The paddings, before and after for each spatial dimension
+ * of the input tensor.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0.
+ */
+ PAD = 32,
+
+ /**
+ * SpaceToBatch for N-D tensors.
+ *
+ * This operation divides "spatial" dimensions [1, ..., M] of the input into a grid of blocks
+ * of shape block_shape, and interleaves these blocks with the "batch" dimension (0) such that
+ * in the output, the spatial dimensions [1, ..., M] correspond to the position within the grid,
+ * and the batch dimension combines both the position within a spatial block and the original
+ * batch position. Prior to division into blocks, the spatial dimensions of the input are
+ * optionally zero padded according to paddings.
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: An n-D tensor, specifying the input.
+ * 1: A 1-D Tensor of type TENSOR_INT32, the block sizes for each spatial dimension of the
+ * input tensor. All values must be >= 1.
+ * 2: A 2-D Tensor of type TENSOR_INT32, the paddings for each spatial diemension of the
+ * input tensor. All values must be >= 0.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0.
+ */
+ SPACE_TO_BATCH_ND = 33,
+
+ /**
+ * Removes dimensions of size 1 from the shape of a tensor.
+ *
+ * Given a tensor input, this operation returns a tensor of the same type with all
+ * dimensions of size 1 removed. If you don't want to remove all size 1 dimensions,
+ * you can remove specific size 1 dimensions by specifying axis.
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: An n-D tensor, specifying the input.
+ * 1: An 1-D Tensor of type TENSOR_INT32. The dimensions to squeeze. If None (the default),
+ * squeezes all dimensions. If specified, only squeezes the dimensions listed. The dimension
+ * index starts at 0. It is an error to squeeze a dimension that is not 1.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0. Contains the same data as input, but has one or more
+ * dimensions of size 1 removed.
+ */
+ SQUEEZE = 34,
+
+ /**
+ * Extracts a strided slice of a tensor.
+ *
+ * This op extracts a slice of size (end-begin)/stride from the given input tensor.
+ * Starting at the location specified by begin the slice continues by adding
+ * stride to the index until all dimensions are not less than end. Note that a stride can
+ * be negative, which causes a reverse slice.
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: An n-D tensor, specifying the input.
+ * 1: A 1-D Tensor of type TENSOR_INT32, the starts of the dimensions of the input
+ * tensor to be sliced.
+ * 2: A 1-D Tensor of type TENSOR_INT32, the ends of the dimensions of the input
+ * tensor to be sliced.
+ * 3: A 1-D Tensor of type TENSOR_INT32, the strides of the dimensions of the input
+ * tensor to be sliced.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0.
+ */
+ STRIDED_SLICE = 35,
+
+ /**
+ * Subtracts the second tensor from the first tensor, element-wise.
+ *
+ * Takes two input tensors of identical type and compatible dimensions. The output
+ * is the result of subtracting the second input tensor from the first one, optionally
+ * modified by an activation function.
+ *
+ * Two dimensions are compatible when:
+ * 1. they are equal, or
+ * 2. one of them is 1
+ *
+ * The size of the output is the maximum size along each dimension of the input operands.
+ * It starts with the trailing dimensions, and works its way forward.
+ *
+ * Example:
+ * input1.dimension = {4, 1, 2}
+ * input2.dimension = {5, 4, 3, 1}
+ * output.dimension = {5, 4, 3, 2}
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: An n-D tensor, specifying the first input.
+ * 1: A tensor of the same type, and compatible dimensions as input0.
+ * 2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+ * Specifies the activation to invoke on the result of each addition.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0.
+ */
+ SUB = 36,
+
+ /**
+ * Transposes the input tensor, permuting the dimensions according to the perm tensor.
+ *
+ * The returned tensor's dimension i must correspond to the input dimension perm[i].
+ * If perm is not given, it is set to (n-1...0), where n is the rank of the input tensor.
+ * Hence by default, this operation performs a regular matrix transpose on 2-D input Tensors.
+ *
+ * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor rank: up to 4
+ *
+ * Inputs:
+ * 0: An n-D tensor, specifying the input.
+ * 1: A 1-D Tensor of type TENSOR_INT32, the permutation of the dimensions of the input
+ * tensor.
+ *
+ * Outputs:
+ * 0: A tensor of the same type as input0.
+ */
+ TRANSPOSE = 37,
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+ /**
+ * The operation type.
+ */
+ OperationType type;
+
+ /**
+ * Describes the table that contains the indexes of the inputs of the
+ * operation. The offset is the index in the operandIndexes table.
+ */
+ vec<uint32_t> inputs;
+
+ /**
+ * Describes the table that contains the indexes of the outputs of the
+ * operation. The offset is the index in the operandIndexes table.
+ */
+ vec<uint32_t> outputs;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * may not be known is the shape of the input tensors.
+ */
+struct Model {
+ /**
+ * All operands included in the model.
+ */
+ vec<Operand> operands;
+
+ /**
+ * All operations included in the model.
+ *
+ * The operations are sorted into execution order.
+ */
+ vec<Operation> operations;
+
+ /**
+ * Input indexes of the model.
+ *
+ * Each value corresponds to the index of the operand in "operands".
+ */
+ vec<uint32_t> inputIndexes;
+
+ /**
+ * Output indexes of the model.
+ *
+ * Each value corresponds to the index of the operand in "operands".
+ */
+ vec<uint32_t> outputIndexes;
+
+ /**
+ * A byte buffer containing operand data that were copied into the model.
+ *
+ * An operand's value must be located here if and only if Operand::lifetime
+ * equals OperandLifeTime::CONSTANT_COPY.
+ */
+ vec<uint8_t> operandValues;
+
+ /**
+ * A collection of shared memory pools containing operand data that were
+ * registered by the model.
+ *
+ * An operand's value must be located here if and only if Operand::lifetime
+ * equals OperandLifeTime::CONSTANT_REFERENCE.
+ */
+ vec<memory> pools;
+};
diff --git a/neuralnetworks/README b/neuralnetworks/README
new file mode 100644
index 0000000..d8c8f5d
--- /dev/null
+++ b/neuralnetworks/README
@@ -0,0 +1,2 @@
+NeuralNetworks sample driver implementation is located at
+frameworks/ml/nn/driver/sample.
diff --git a/nfc/1.1/Android.bp b/nfc/1.1/Android.bp
new file mode 100644
index 0000000..73dc70a
--- /dev/null
+++ b/nfc/1.1/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.nfc@1.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "INfc.hal",
+ "INfcClientCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.nfc@1.0",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "NfcEvent",
+ ],
+ gen_java: true,
+}
+
diff --git a/nfc/1.1/INfc.hal b/nfc/1.1/INfc.hal
new file mode 100644
index 0000000..ea6a571
--- /dev/null
+++ b/nfc/1.1/INfc.hal
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+package android.hardware.nfc@1.1;
+
+import @1.1::INfcClientCallback;
+import @1.0::INfc;
+import @1.0::NfcStatus;
+
+interface INfc extends @1.0::INfc {
+ /**
+ * Clears the NFC chip.
+ *
+ * Must be called during factory reset and/or before the first time the HAL is
+ * initialized after a factory reset
+ */
+ factoryReset();
+
+ /**
+ * Enable Power off use cases and close the NFC controller.
+ * Should free all resources.
+ *
+ * This call must enable NFC functionality for off host usecases in power
+ * off use cases, if the device supports power off use cases. If the
+ * device doesn't support power off use cases, this call should be same as
+ * close()
+ *
+ * @return NfcStatus::OK on success and NfcStatus::FAILED on error.
+ */
+ closeForPowerOffCase() generates (NfcStatus status);
+
+ /**
+ * Open call to take the @1.1::INfcClientCallback
+ *
+ * @param clientCallback for sending events and data to client.
+ * @return status NfcStatus::FAILED in case of error,
+ * NfcStatus::SUCCESS otherwise.
+ */
+ open_1_1(INfcClientCallback clientCallback) generates (NfcStatus status);
+};
diff --git a/nfc/1.1/INfcClientCallback.hal b/nfc/1.1/INfcClientCallback.hal
new file mode 100644
index 0000000..8e1a7bc
--- /dev/null
+++ b/nfc/1.1/INfcClientCallback.hal
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.nfc@1.1;
+
+import @1.0::INfcClientCallback;
+import @1.0::NfcStatus;
+
+interface INfcClientCallback extends @1.0::INfcClientCallback {
+ /**
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass events back to the stack.
+ */
+ sendEvent_1_1(NfcEvent event, NfcStatus status);
+};
diff --git a/nfc/1.1/types.hal b/nfc/1.1/types.hal
new file mode 100644
index 0000000..2f5ec7f
--- /dev/null
+++ b/nfc/1.1/types.hal
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+package android.hardware.nfc@1.1;
+
+import @1.0::NfcEvent;
+
+enum NfcEvent : @1.0::NfcEvent {
+ /** In case of an error, HCI network needs to be re-initialized */
+ HCI_NETWORK_RESET = 7
+};
diff --git a/nfc/1.1/vts/functional/Android.bp b/nfc/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..0ce531f
--- /dev/null
+++ b/nfc/1.1/vts/functional/Android.bp
@@ -0,0 +1,25 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_test {
+ name: "VtsHalNfcV1_1TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalNfcV1_1TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.nfc@1.0",
+ "android.hardware.nfc@1.1",
+ ],
+}
diff --git a/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
new file mode 100644
index 0000000..a5b40d4
--- /dev/null
+++ b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 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 "nfc_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/nfc/1.0/types.h>
+#include <android/hardware/nfc/1.1/INfc.h>
+#include <android/hardware/nfc/1.1/INfcClientCallback.h>
+#include <android/hardware/nfc/1.1/types.h>
+#include <hardware/nfc.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+
+using ::android::hardware::nfc::V1_1::INfc;
+using ::android::hardware::nfc::V1_1::INfcClientCallback;
+using ::android::hardware::nfc::V1_1::NfcEvent;
+using ::android::hardware::nfc::V1_0::NfcStatus;
+using ::android::hardware::nfc::V1_0::NfcData;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+constexpr char kCallbackNameSendEvent[] = "sendEvent";
+constexpr char kCallbackNameSendData[] = "sendData";
+
+class NfcClientCallbackArgs {
+ public:
+ NfcEvent last_event_;
+ NfcStatus last_status_;
+ NfcData last_data_;
+};
+
+/* Callback class for data & Event. */
+class NfcClientCallback : public ::testing::VtsHalHidlTargetCallbackBase<NfcClientCallbackArgs>,
+ public INfcClientCallback {
+ public:
+ virtual ~NfcClientCallback() = default;
+
+ /* sendEvent callback function - Records the Event & Status
+ * and notifies the TEST
+ **/
+ Return<void> sendEvent_1_1(NfcEvent event, NfcStatus event_status) override {
+ NfcClientCallbackArgs args;
+ args.last_event_ = event;
+ args.last_status_ = event_status;
+ NotifyFromCallback(kCallbackNameSendEvent, args);
+ return Void();
+ };
+
+ /** NFC 1.1 HAL shouldn't send 1.0 callbacks */
+ Return<void> sendEvent(__attribute__((unused))::android::hardware::nfc::V1_0::NfcEvent event,
+ __attribute__((unused)) NfcStatus event_status) override {
+ return Void();
+ }
+
+ /* sendData callback function. Records the data and notifies the TEST*/
+ Return<void> sendData(const NfcData& data) override {
+ NfcClientCallbackArgs args;
+ args.last_data_ = data;
+ NotifyFromCallback(kCallbackNameSendData, args);
+ return Void();
+ };
+};
+
+// The main test class for NFC HIDL HAL.
+class NfcHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ nfc_ = ::testing::VtsHalHidlTargetTestBase::getService<INfc>();
+ ASSERT_NE(nfc_, nullptr);
+
+ nfc_cb_ = new NfcClientCallback();
+ ASSERT_NE(nfc_cb_, nullptr);
+
+ EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+ // Wait for OPEN_CPLT event
+ auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+ /*
+ * Close the hal and then re-open to make sure we are in a predictable
+ * state for all the tests.
+ */
+ EXPECT_EQ(NfcStatus::OK, nfc_->close());
+ // Wait for CLOSE_CPLT event
+ res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+ EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+ // Wait for OPEN_CPLT event
+ res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+ }
+
+ virtual void TearDown() override {
+ EXPECT_EQ(NfcStatus::OK, nfc_->close());
+ // Wait for CLOSE_CPLT event
+ auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+ }
+
+ sp<INfc> nfc_;
+ sp<NfcClientCallback> nfc_cb_;
+};
+
+// A class for test environment setup (kept since this file is a template).
+class NfcHidlEnvironment : public ::testing::Environment {
+ public:
+ virtual void SetUp() {}
+ virtual void TearDown() {}
+
+ private:
+};
+
+/*
+ * factoryReset
+ * calls factoryReset()
+ * checks status
+ */
+TEST_F(NfcHidlTest, FactoryReset) {
+ nfc_->factoryReset();
+
+ EXPECT_EQ(NfcStatus::OK, nfc_->close());
+ // Wait for CLOSE_CPLT event
+ auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+ EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+ // Wait for OPEN_CPLT event
+ res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+}
+
+/*
+ * OpenAndClose:
+ * Makes an open call, waits for NfcEvent.OPEN_CPLT
+ * Immediately calls closeforPowerOffCase() and waits for NfcEvent.CLOSE_CPLT
+ */
+TEST_F(NfcHidlTest, OpenAndCloseForPowerOff) {
+ EXPECT_EQ(NfcStatus::OK, nfc_->closeForPowerOffCase());
+ // Wait for CLOSE_CPLT event
+ auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+ EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+ // Wait for OPEN_CPLT event
+ res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+}
+
+/*
+ * CloseForPowerOffCaseAfterClose:
+ * Calls closeForPowerOffCase()
+ * Calls close() - checks failed status
+ */
+TEST_F(NfcHidlTest, CloseForPowerCaseOffAfterClose) {
+ EXPECT_EQ(NfcStatus::OK, nfc_->closeForPowerOffCase());
+ // Wait for CLOSE_CPLT event
+ auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+ EXPECT_EQ(NfcStatus::FAILED, nfc_->close());
+
+ EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+ // Wait for OPEN_CPLT event
+ res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+}
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(new NfcHidlEnvironment);
+ ::testing::InitGoogleTest(&argc, argv);
+
+ std::system("svc nfc disable"); /* Turn off NFC */
+ sleep(5);
+
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+
+ std::system("svc nfc enable"); /* Turn on NFC */
+ sleep(5);
+
+ return status;
+}
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index f4ca1cf..552e33d 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -19,6 +19,8 @@
"android.hidl.base@1.0",
],
types: [
+ "AudioQuality",
+ "Call",
"CardStatus",
"CellConnectionStatus",
"CellIdentityCdma",
diff --git a/radio/1.2/IRadioResponse.hal b/radio/1.2/IRadioResponse.hal
index c356954..93ec4d7 100644
--- a/radio/1.2/IRadioResponse.hal
+++ b/radio/1.2/IRadioResponse.hal
@@ -72,4 +72,20 @@
* RadioError:INTERNAL_ERR
*/
oneway setLinkCapacityReportingCriteriaResponse(RadioResponseInfo info);
+
+ /**
+ * @param calls Current call list
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:NO_MEMORY
+ * RadioError:INTERNAL_ERR
+ * RadioError:SYSTEM_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ */
+ oneway getCurrentCallsResponse_1_2(RadioResponseInfo info, vec<Call> calls);
};
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index f2f0b69..c353645 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -16,6 +16,7 @@
package android.hardware.radio@1.2;
+import @1.0::Call;
import @1.0::CdmaSignalStrength;
import @1.0::CardState;
import @1.0::CardStatus;
@@ -125,6 +126,33 @@
PHYSICAL_CHANNEL_CONFIG = 1 << 4,
};
+/**
+ * Audio codec which is used on GSM, UMTS, and CDMA. These values must be opaque
+ * to the Android framework. Only for display.
+ */
+enum AudioQuality : int32_t {
+ /** Unspecified audio codec */
+ UNSPECIFIED,
+ /** AMR (Narrowband) audio codec */
+ AMR,
+ /** AMR (Wideband) audio codec */
+ AMR_WB,
+ /** GSM Enhanced Full-Rate audio codec */
+ GSM_EFR,
+ /** GSM Full-Rate audio codec */
+ GSM_FR,
+ /** GSM Half-Rate audio codec */
+ GSM_HR,
+ /** Enhanced Variable rate codec */
+ EVRC,
+ /** Enhanced Variable rate codec revision B */
+ EVRC_B,
+ /** Enhanced Variable rate codec (Wideband) */
+ EVRC_WB,
+ /** Enhanced Variable rate codec (Narrowband) */
+ EVRC_NW,
+};
+
struct NetworkScanRequest {
ScanType type;
@@ -364,3 +392,8 @@
*/
HANDOVER = 0x03,
};
+
+struct Call {
+ @1.0::Call base;
+ AudioQuality audioQuality;
+};
diff --git a/secure_element/1.0/Android.bp b/secure_element/1.0/Android.bp
new file mode 100644
index 0000000..e8081df
--- /dev/null
+++ b/secure_element/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.secure_element@1.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "ISecureElement.hal",
+ "ISecureElementHalCallback.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "LogicalChannelResponse",
+ "SecureElementStatus",
+ ],
+ gen_java: true,
+}
+
diff --git a/secure_element/1.0/ISecureElement.hal b/secure_element/1.0/ISecureElement.hal
new file mode 100644
index 0000000..d1e36f7
--- /dev/null
+++ b/secure_element/1.0/ISecureElement.hal
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package android.hardware.secure_element@1.0;
+
+import ISecureElementHalCallback;
+
+/** According to ISO/IEC 7816 */
+interface ISecureElement {
+ /**
+ * Initializes the Secure Element. This may include updating the applet
+ * and/or vendor-specific initialization.
+ *
+ * HAL service must send onStateChange() with connected equal to true
+ * after all the initialization has been successfully completed.
+ * Clients must wait for a onStateChange(true) before opening channels.
+ *
+ * @param clientCallback callback used to sent status of the SE back to the
+ * client
+ */
+ init(ISecureElementHalCallback clientCallback);
+
+ /**
+ * Returns Answer to Reset as per ISO/IEC 7816
+ *
+ * @return response containing the response. Empty vector if Secure Element
+ * doesn't support ATR.
+ */
+ getAtr() generates (vec<uint8_t> response);
+
+ /**
+ * Returns the current state of the card.
+ *
+ * This is particularly useful for removable
+ * Secure Elements like UICC, Secure Elements on SD cards etc.
+ *
+ * @return present true if present, false otherwise
+ */
+ isCardPresent() generates (bool present);
+
+ /**
+ * Transmits an APDU command (as per ISO/IEC 7816) to the SE.
+ *
+ * @param data APDU command to be sent
+ * @return response to the command. In case of error in communicating with
+ * the secure element, an empty vector is returned.
+ */
+ transmit(vec<uint8_t> data) generates (vec<uint8_t> response);
+
+ /**
+ * Opens a logical channel with the Secure Element, selecting the applet
+ * represented by the Application ID (AID).
+ *
+ * @param aid AID to uniquely identify the applet on the Secure Element
+ * @param p2 P2 paramter of SELECT APDU as per ISO 7816-4
+ * @return status SecureElementStatus::SUCCESS on success,
+ * SecureElementStatus::CHANNEL_NOT_AVAILABLE if secure
+ * element has reached the maximum limit on the number of
+ * channels it can support,
+ * SecureElementStatus::NO_SUCH_ELEMENT_ERROR if AID provided
+ * doesn't match any applet on the secure element and
+ * SecureElementStatus::UNSUPPORTED_OPERATION if operation
+ * provided by the P2 parameter is not permitted by the
+ * applet.
+ * SecureElementStatus::IOERROR if there was an error
+ * communicating with the Secure Element.
+ * @return response On success, response to SELECT command is returned
+ * empty vector on failure.
+ */
+ openLogicalChannel(vec<uint8_t> aid, uint8_t p2)
+ generates (LogicalChannelResponse response, SecureElementStatus status);
+
+
+ /**
+ * Opens a basic channel with the Secure Element, selecting the applet
+ * represented by the Application ID (AID).
+ *
+ * @param aid AID to uniquely identify the applet on the Secure Element
+ * @param p2 P2 paramter of SELECT APDU as per ISO 7816-4
+ * @return status SecureElementStatus::SUCCESS on success,
+ * SecureElementStatus::CHANNEL_NOT_AVAILABLE if secure
+ * element has reached the maximum limit on the number of
+ * channels it can support,
+ * SecureElementStatus::NO_SUCH_ELEMENT_ERROR if AID provided
+ * doesn't match any applet on the secure element and
+ * SecureElementStatus::UNSUPPORTED_OPERATION if operation
+ * provided by the P2 parameter is not permitted by the
+ * applet.
+ * SecureElementStatus::IOERROR if there was an error
+ * communicating with the Secure Element.
+ * @return selectResponse On success, response to SELECT command is returned
+ * empty vector on failure.
+ */
+ openBasicChannel(vec<uint8_t> aid, uint8_t p2)
+ generates (vec<uint8_t> selectResponse, SecureElementStatus status);
+
+ /**
+ * Closes the channel indicated by the channelNumber.
+ *
+ * Closing a basic channel, i.e with channelNumber 0 must return
+ * SecureElementStatus::FAILED.
+ *
+ * @param channelNumber to be closed
+ * @return status SecureElementStatus::SUCCESS on success and
+ * SecureElementStatus::FAILED on error.
+ */
+ closeChannel(uint8_t channelNumber) generates (SecureElementStatus status);
+};
diff --git a/secure_element/1.0/ISecureElementHalCallback.hal b/secure_element/1.0/ISecureElementHalCallback.hal
new file mode 100644
index 0000000..d11600f
--- /dev/null
+++ b/secure_element/1.0/ISecureElementHalCallback.hal
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package android.hardware.secure_element@1.0;
+
+interface ISecureElementHalCallback {
+ onStateChange(bool connected);
+};
diff --git a/secure_element/1.0/types.hal b/secure_element/1.0/types.hal
new file mode 100644
index 0000000..8150be4
--- /dev/null
+++ b/secure_element/1.0/types.hal
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package android.hardware.secure_element@1.0;
+
+enum SecureElementStatus : uint8_t {
+ SUCCESS = 0,
+ FAILED = 1,
+ CHANNEL_NOT_AVAILABLE = 2,
+ NO_SUCH_ELEMENT_ERROR = 3,
+ UNSUPPORTED_OPERATION = 4,
+ IOERROR = 5
+};
+
+struct LogicalChannelResponse {
+ /** Channel number to uniquely identify the channel */
+ uint8_t channelNumber;
+ /** Response to SELECT command as per ISO/IEC 7816 */
+ vec<uint8_t> selectResponse;
+};
diff --git a/secure_element/1.0/vts/functional/Android.bp b/secure_element/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..752df9e
--- /dev/null
+++ b/secure_element/1.0/vts/functional/Android.bp
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_test {
+ name: "VtsHalSecureElementV1_0TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalSecureElementV1_0TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.secure_element@1.0",
+ ],
+}
diff --git a/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
new file mode 100644
index 0000000..2045e44
--- /dev/null
+++ b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2018 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 "secure_element_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/secure_element/1.0/ISecureElement.h>
+#include <android/hardware/secure_element/1.0/ISecureElementHalCallback.h>
+#include <android/hardware/secure_element/1.0/types.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::hardware::secure_element::V1_0::ISecureElement;
+using ::android::hardware::secure_element::V1_0::ISecureElementHalCallback;
+using ::android::hardware::secure_element::V1_0::SecureElementStatus;
+using ::android::hardware::secure_element::V1_0::LogicalChannelResponse;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::testing::VtsHalHidlTargetTestEnvBase;
+
+#define SELECT_ISD \
+ { 0x00, 0xA4, 0x04, 0x00, 0x00 }
+#define SEQUENCE_COUNTER \
+ { 0x80, 0xCA, 0x00, 0xC1, 0x00 }
+#define MANAGE_SELECT \
+ { 0x00, 0xA4, 0x04, 0x00, 0x00 }
+#define CRS_AID \
+ { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x43, 0x52, 0x53, 0x00 }
+
+constexpr char kCallbackNameOnStateChange[] = "onStateChange";
+
+class SecureElementCallbackArgs {
+ public:
+ bool state_;
+};
+
+class SecureElementHalCallback
+ : public ::testing::VtsHalHidlTargetCallbackBase<SecureElementCallbackArgs>,
+ public ISecureElementHalCallback {
+ public:
+ virtual ~SecureElementHalCallback() = default;
+
+ Return<void> onStateChange(bool state) override {
+ SecureElementCallbackArgs args;
+ args.state_ = state;
+ NotifyFromCallback(kCallbackNameOnStateChange, args);
+ return Void();
+ };
+};
+
+class SecureElementHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static SecureElementHidlEnvironment* Instance() {
+ static SecureElementHidlEnvironment* instance = new SecureElementHidlEnvironment;
+ return instance;
+ }
+
+ virtual void registerTestServices() override { registerTestService<ISecureElement>(); }
+
+ private:
+ SecureElementHidlEnvironment() {}
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SecureElementHidlEnvironment);
+};
+
+class SecureElementHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ std::string serviceName =
+ SecureElementHidlEnvironment::Instance()->getServiceName<ISecureElement>("eSE1");
+ LOG(INFO) << "get service with name:" << serviceName;
+ ASSERT_FALSE(serviceName.empty());
+ se_ = ::testing::VtsHalHidlTargetTestBase::getService<ISecureElement>(serviceName);
+ ASSERT_NE(se_, nullptr);
+
+ se_cb_ = new SecureElementHalCallback();
+ ASSERT_NE(se_cb_, nullptr);
+ }
+
+ sp<ISecureElement> se_;
+ sp<SecureElementHalCallback> se_cb_;
+};
+
+/*
+ * isCardPresent:
+ * Expects the card to be present
+ */
+TEST_F(SecureElementHidlTest, isCardPresent) {
+ EXPECT_TRUE(se_->isCardPresent());
+}
+
+/*
+ * transmit:
+ * Check status word in the response
+ */
+TEST_F(SecureElementHidlTest, transmit) {
+ std::vector<uint8_t> aid = CRS_AID;
+ SecureElementStatus statusReturned;
+ LogicalChannelResponse response;
+ se_->openLogicalChannel(
+ aid, 0x00,
+ [&statusReturned, &response](LogicalChannelResponse channelResponse,
+ SecureElementStatus status) {
+ statusReturned = status;
+ if (status == SecureElementStatus::SUCCESS) {
+ response.channelNumber = channelResponse.channelNumber;
+ response.selectResponse.resize(channelResponse.selectResponse.size());
+ for (size_t i = 0; i < channelResponse.selectResponse.size(); i++) {
+ response.selectResponse[i] = channelResponse.selectResponse[i];
+ }
+ }
+ });
+ EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned);
+ EXPECT_LE((unsigned int)3, response.selectResponse.size());
+ EXPECT_LE(1, response.channelNumber);
+ std::vector<uint8_t> command = SELECT_ISD;
+ std::vector<uint8_t> transmitResponse;
+ se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
+ transmitResponse.resize(res.size());
+ for (size_t i = 0; i < res.size(); i++) {
+ transmitResponse[i] = res[i];
+ }
+ });
+ EXPECT_LE((unsigned int)3, transmitResponse.size());
+ EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
+ EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
+ command = SEQUENCE_COUNTER;
+ se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
+ transmitResponse.resize(res.size());
+ for (size_t i = 0; i < res.size(); i++) {
+ transmitResponse[i] = res[i];
+ }
+ });
+ EXPECT_LE((unsigned int)3, transmitResponse.size());
+ EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
+ EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
+ EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
+}
+
+/*
+ * OpenCloseBasicChannel:
+ * If the secure element allows opening of basic channel:
+ * open channel, check the length of selectResponse and close the channel
+ */
+TEST_F(SecureElementHidlTest, openBasicChannel) {
+ std::vector<uint8_t> aid = CRS_AID;
+ SecureElementStatus statusReturned;
+ std::vector<uint8_t> response;
+ se_->openBasicChannel(aid, 0x00,
+ [&statusReturned, &response](std::vector<uint8_t> selectResponse,
+ SecureElementStatus status) {
+ statusReturned = status;
+ if (status == SecureElementStatus::SUCCESS) {
+ response.resize(selectResponse.size());
+ for (size_t i = 0; i < selectResponse.size(); i++) {
+ response[i] = selectResponse[i];
+ }
+ }
+ });
+ if (statusReturned == SecureElementStatus::SUCCESS) {
+ EXPECT_LE((unsigned int)3, response.size());
+ std::vector<uint8_t> command = SELECT_ISD;
+ std::vector<uint8_t> transmitResponse;
+ se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
+ transmitResponse.resize(res.size());
+ for (size_t i = 0; i < res.size(); i++) {
+ transmitResponse[i] = res[i];
+ }
+ });
+ EXPECT_LE((unsigned int)3, transmitResponse.size());
+ EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
+ EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
+ return;
+ }
+ EXPECT_EQ(SecureElementStatus::UNSUPPORTED_OPERATION, statusReturned);
+}
+
+/*
+ * GetATR
+ */
+TEST_F(SecureElementHidlTest, getAtr) {
+ std::vector<uint8_t> atr;
+ se_->getAtr([&atr](std::vector<uint8_t> atrReturned) {
+ atr.resize(atrReturned.size());
+ for (size_t i = 0; i < atrReturned.size(); i++) {
+ atr[i] = atrReturned[i];
+ }
+ });
+ if (atr.size() == 0) {
+ return;
+ }
+ EXPECT_GE((unsigned int)32, atr.size());
+ EXPECT_LE((unsigned int)1, atr.size());
+}
+
+/*
+ * OpenCloseLogicalChannel:
+ * Open Channel
+ * Check status
+ * Close Channel
+ */
+TEST_F(SecureElementHidlTest, openCloseLogicalChannel) {
+ std::vector<uint8_t> aid = CRS_AID;
+ SecureElementStatus statusReturned;
+ LogicalChannelResponse response;
+ se_->openLogicalChannel(
+ aid, 0x00,
+ [&statusReturned, &response](LogicalChannelResponse channelResponse,
+ SecureElementStatus status) {
+ statusReturned = status;
+ if (status == SecureElementStatus::SUCCESS) {
+ response.channelNumber = channelResponse.channelNumber;
+ response.selectResponse.resize(channelResponse.selectResponse.size());
+ for (size_t i = 0; i < channelResponse.selectResponse.size(); i++) {
+ response.selectResponse[i] = channelResponse.selectResponse[i];
+ }
+ }
+ });
+ EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned);
+ EXPECT_LE((unsigned int)3, response.selectResponse.size());
+ EXPECT_LE(1, response.channelNumber);
+ EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
+}
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(SecureElementHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ SecureElementHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ return status;
+}
diff --git a/tests/extension/light/2.0/types.hal b/tests/extension/light/2.0/types.hal
index c05e099..4463cac 100644
--- a/tests/extension/light/2.0/types.hal
+++ b/tests/extension/light/2.0/types.hal
@@ -41,7 +41,7 @@
/**
* Sometimes at night, we need it to be day.
*/
- THE_SUN,
+ THE_SUN,
};
/**
diff --git a/wifi/1.2/default/ringbuffer.cpp b/wifi/1.2/default/ringbuffer.cpp
index 5511f2f..c126b36 100644
--- a/wifi/1.2/default/ringbuffer.cpp
+++ b/wifi/1.2/default/ringbuffer.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <android-base/logging.h>
+
#include "ringbuffer.h"
namespace android {
@@ -28,6 +30,11 @@
if (input.size() == 0) {
return;
}
+ if (input.size() > maxSize_) {
+ LOG(INFO) << "Oversized message of " << input.size()
+ << " bytes is dropped";
+ return;
+ }
data_.push_back(input);
size_ += input.size() * sizeof(input[0]);
while (size_ > maxSize_) {
diff --git a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
index 1b332f9..ad5289b 100644
--- a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
+++ b/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
@@ -81,6 +81,15 @@
buffer_.append(input);
ASSERT_TRUE(buffer_.getData().empty());
}
+
+TEST_F(RingbufferTest, OversizedAppendDoesNotDropExistingData) {
+ const std::vector<uint8_t> input(maxBufferSize_, '0');
+ const std::vector<uint8_t> input2(maxBufferSize_ + 1, '1');
+ buffer_.append(input);
+ buffer_.append(input2);
+ ASSERT_EQ(1u, buffer_.getData().size());
+ EXPECT_EQ(input, buffer_.getData().front());
+}
} // namespace implementation
} // namespace V1_2
} // namespace wifi
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index 05ea638..201b8e4 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -123,34 +123,118 @@
std::string cur_file_name(dp->d_name);
struct stat cur_file_stat;
std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
- if (stat(cur_file_path.c_str(), &cur_file_stat) != -1) {
- if (cur_file_stat.st_mtime < delete_files_before) {
- if (unlink(cur_file_path.c_str()) != 0) {
- LOG(ERROR) << "Error deleting file " << strerror(errno);
- success = false;
- }
- }
- } else {
+ if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) {
LOG(ERROR) << "Failed to get file stat for " << cur_file_path
<< ": " << strerror(errno);
success = false;
+ continue;
+ }
+ if (cur_file_stat.st_mtime >= delete_files_before) {
+ continue;
+ }
+ if (unlink(cur_file_path.c_str()) != 0) {
+ LOG(ERROR) << "Error deleting file " << strerror(errno);
+ success = false;
}
}
return success;
}
+// Helper function for |cpioArchiveFilesInDir|
+bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name,
+ size_t file_name_len) {
+ std::array<char, 32 * 1024> read_buf;
+ ssize_t llen =
+ sprintf(read_buf.data(),
+ "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
+ kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid,
+ st.st_gid, static_cast<int>(st.st_nlink),
+ static_cast<int>(st.st_mtime), static_cast<int>(st.st_size),
+ major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
+ minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
+ if (write(out_fd, read_buf.data(), llen) == -1) {
+ LOG(ERROR) << "Error writing cpio header to file " << file_name << " "
+ << strerror(errno);
+ return false;
+ }
+ if (write(out_fd, file_name, file_name_len) == -1) {
+ LOG(ERROR) << "Error writing filename to file " << file_name << " "
+ << strerror(errno);
+ return false;
+ }
+
+ // NUL Pad header up to 4 multiple bytes.
+ llen = (llen + file_name_len) % 4;
+ if (llen != 0) {
+ const uint32_t zero = 0;
+ if (write(out_fd, &zero, 4 - llen) == -1) {
+ LOG(ERROR) << "Error padding 0s to file " << file_name << " "
+ << strerror(errno);
+ return false;
+ }
+ }
+ return true;
+}
+
+// Helper function for |cpioArchiveFilesInDir|
+size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
+ // writing content of file
+ std::array<char, 32 * 1024> read_buf;
+ ssize_t llen = st.st_size;
+ size_t n_error = 0;
+ while (llen > 0) {
+ ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
+ if (bytes_read == -1) {
+ LOG(ERROR) << "Error reading file " << strerror(errno);
+ return ++n_error;
+ }
+ llen -= bytes_read;
+ if (write(out_fd, read_buf.data(), bytes_read) == -1) {
+ LOG(ERROR) << "Error writing data to file " << strerror(errno);
+ return ++n_error;
+ }
+ if (bytes_read == 0) { // this should never happen, but just in case
+ // to unstuck from while loop
+ LOG(ERROR) << "Unexpected read result for " << strerror(errno);
+ n_error++;
+ break;
+ }
+ }
+ llen = st.st_size % 4;
+ if (llen != 0) {
+ const uint32_t zero = 0;
+ if (write(out_fd, &zero, 4 - llen) == -1) {
+ LOG(ERROR) << "Error padding 0s to file " << strerror(errno);
+ return ++n_error;
+ }
+ }
+ return n_error;
+}
+
+// Helper function for |cpioArchiveFilesInDir|
+bool cpioWriteFileTrailer(int out_fd) {
+ std::array<char, 4096> read_buf;
+ read_buf.fill(0);
+ if (write(out_fd, read_buf.data(),
+ sprintf(read_buf.data(), "070701%040X%056X%08XTRAILER!!!", 1,
+ 0x0b, 0) +
+ 4) == -1) {
+ LOG(ERROR) << "Error writing trailing bytes " << strerror(errno);
+ return false;
+ }
+ return true;
+}
+
// Archives all files in |input_dir| and writes result into |out_fd|
// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
// portion
-size_t cpioFilesInDir(int out_fd, const char* input_dir) {
+size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
struct dirent* dp;
size_t n_error = 0;
- char read_buf[32 * 1024];
DIR* dir_dump = opendir(input_dir);
if (!dir_dump) {
LOG(ERROR) << "Failed to open directory: " << strerror(errno);
- n_error++;
- return n_error;
+ return ++n_error;
}
unique_fd dir_auto_closer(dirfd(dir_dump));
while ((dp = readdir(dir_dump))) {
@@ -158,99 +242,36 @@
continue;
}
std::string cur_file_name(dp->d_name);
- const size_t file_name_len =
- cur_file_name.size() + 1; // string.size() does not include the
- // null terminator. The cpio FreeBSD file
- // header expects the null character to
- // be included in the length.
+ // string.size() does not include the null terminator. The cpio FreeBSD
+ // file header expects the null character to be included in the length.
+ const size_t file_name_len = cur_file_name.size() + 1;
struct stat st;
- ssize_t llen;
const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
- if (stat(cur_file_path.c_str(), &st) != -1) {
- const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
- unique_fd file_auto_closer(fd_read);
- if (fd_read == -1) {
- LOG(ERROR) << "Failed to read file " << cur_file_path << " "
- << strerror(errno);
- n_error++;
- continue;
- }
- llen = sprintf(
- read_buf,
- "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
- kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid,
- st.st_gid, static_cast<int>(st.st_nlink),
- static_cast<int>(st.st_mtime), static_cast<int>(st.st_size),
- major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
- minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
- if (write(out_fd, read_buf, llen) == -1) {
- LOG(ERROR) << "Error writing cpio header to file "
- << cur_file_path << " " << strerror(errno);
- n_error++;
- return n_error;
- }
- if (write(out_fd, cur_file_name.c_str(), file_name_len) == -1) {
- LOG(ERROR) << "Error writing filename to file " << cur_file_path
- << " " << strerror(errno);
- n_error++;
- return n_error;
- }
-
- // NUL Pad header up to 4 multiple bytes.
- llen = (llen + file_name_len) % 4;
- if (llen != 0) {
- const uint32_t zero = 0;
- if (write(out_fd, &zero, 4 - llen) == -1) {
- LOG(ERROR) << "Error padding 0s to file " << cur_file_path
- << " " << strerror(errno);
- n_error++;
- return n_error;
- }
- }
-
- // writing content of file
- llen = st.st_size;
- while (llen > 0) {
- ssize_t bytes_read = read(fd_read, read_buf, sizeof(read_buf));
- if (bytes_read == -1) {
- LOG(ERROR) << "Error reading file " << cur_file_path << " "
- << strerror(errno);
- n_error++;
- return n_error;
- }
- llen -= bytes_read;
- if (write(out_fd, read_buf, bytes_read) == -1) {
- LOG(ERROR) << "Error writing data to file " << cur_file_path
- << " " << strerror(errno);
- n_error++;
- return n_error;
- }
- if (bytes_read ==
- 0) { // this should never happen, but just in case
- // to unstuck from while loop
- LOG(ERROR) << "Unexpected file size for " << cur_file_path
- << " " << strerror(errno);
- n_error++;
- break;
- }
- }
- llen = st.st_size % 4;
- if (llen != 0) {
- const uint32_t zero = 0;
- write(out_fd, &zero, 4 - llen);
- }
- } else {
+ if (stat(cur_file_path.c_str(), &st) == -1) {
LOG(ERROR) << "Failed to get file stat for " << cur_file_path
<< ": " << strerror(errno);
n_error++;
+ continue;
+ }
+ const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
+ if (fd_read == -1) {
+ LOG(ERROR) << "Failed to open file " << cur_file_path << " "
+ << strerror(errno);
+ n_error++;
+ continue;
+ }
+ unique_fd file_auto_closer(fd_read);
+ if (!cpioWriteHeader(out_fd, st, cur_file_name.c_str(),
+ file_name_len)) {
+ return ++n_error;
+ }
+ size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
+ if (write_error) {
+ return n_error + write_error;
}
}
- memset(read_buf, 0, sizeof(read_buf));
- if (write(out_fd, read_buf,
- sprintf(read_buf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0) +
- 4) == -1) {
- LOG(ERROR) << "Error writing trailing bytes " << strerror(errno);
- n_error++;
+ if (!cpioWriteFileTrailer(out_fd)) {
+ return ++n_error;
}
return n_error;
}
@@ -541,7 +562,7 @@
if (!writeRingbufferFilesInternal()) {
LOG(ERROR) << "Error writing files to flash";
}
- uint32_t n_error = cpioFilesInDir(fd, kTombstoneFolderPath);
+ uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
if (n_error != 0) {
LOG(ERROR) << n_error << " errors occured in cpio function";
}
diff --git a/wifi/hostapd/1.0/IHostapd.hal b/wifi/hostapd/1.0/IHostapd.hal
index 4dc7bf8..3493398 100644
--- a/wifi/hostapd/1.0/IHostapd.hal
+++ b/wifi/hostapd/1.0/IHostapd.hal
@@ -157,4 +157,12 @@
* |HostapdStatusCode.FAILURE_IFACE_UNKNOWN|
*/
removeAccessPoint(string ifaceName) generates(HostapdStatus status);
+
+ /**
+ * Terminate the service.
+ * This must de-register the service and clear all state. If this HAL
+ * supports the lazy HAL protocol, then this may trigger daemon to exit and
+ * wait to be restarted.
+ */
+ oneway terminate();
};
diff --git a/wifi/supplicant/1.1/ISupplicant.hal b/wifi/supplicant/1.1/ISupplicant.hal
index 508a545..f3ec0fc 100644
--- a/wifi/supplicant/1.1/ISupplicant.hal
+++ b/wifi/supplicant/1.1/ISupplicant.hal
@@ -54,4 +54,12 @@
* |SupplicantStatusCode.FAILURE_IFACE_UNKOWN|
*/
removeInterface(IfaceInfo ifaceInfo) generates (SupplicantStatus status);
+
+ /**
+ * Terminate the service.
+ * This must de-register the service and clear all state. If this HAL
+ * supports the lazy HAL protocol, then this may trigger daemon to exit and
+ * wait to be restarted.
+ */
+ oneway terminate();
};