132 lines
5.3 KiB
Java
132 lines
5.3 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2020 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.media.audiofx;
|
||
|
|
||
|
import android.annotation.NonNull;
|
||
|
import android.media.AudioManager;
|
||
|
import android.util.Log;
|
||
|
|
||
|
import java.util.UUID;
|
||
|
|
||
|
/**
|
||
|
* Haptic Generator(HG).
|
||
|
* <p>HG is an audio post-processor which generates haptic data based on the audio channels. The
|
||
|
* generated haptic data is sent along with audio data down to the audio HAL, which will require the
|
||
|
* device to support audio-coupled-haptic playback. In that case, the effect will only be created on
|
||
|
* device supporting audio-coupled-haptic playback. Call {@link HapticGenerator#isAvailable()} to
|
||
|
* check if the device supports this effect.
|
||
|
* <p>An application can create a HapticGenerator object to initiate and control this audio effect
|
||
|
* in the audio framework.
|
||
|
* <p>To attach the HapticGenerator to a particular AudioTrack or MediaPlayer, specify the audio
|
||
|
* session ID of this AudioTrack or MediaPlayer when constructing the HapticGenerator.
|
||
|
* <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
|
||
|
* <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling audio
|
||
|
* effects.
|
||
|
*/
|
||
|
public class HapticGenerator extends AudioEffect implements AutoCloseable {
|
||
|
|
||
|
private static final String TAG = "HapticGenerator";
|
||
|
|
||
|
// For every HapticGenerator, it contains a volume control effect so that the volume control
|
||
|
// will always be handled in the effect chain. In that case, the HapticGenerator can generate
|
||
|
// haptic data based on the raw audio data.
|
||
|
private AudioEffect mVolumeControlEffect;
|
||
|
|
||
|
/**
|
||
|
* @return true if the HapticGenerator is available on the device.
|
||
|
*/
|
||
|
public static boolean isAvailable() {
|
||
|
return AudioManager.isHapticPlaybackSupported()
|
||
|
&& AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_HAPTIC_GENERATOR);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a HapticGenerator and attaches it to the given audio session.
|
||
|
* Use {@link android.media.AudioTrack#getAudioSessionId()} or
|
||
|
* {@link android.media.MediaPlayer#getAudioSessionId()} to
|
||
|
* apply this effect on specific AudioTrack or MediaPlayer instance.
|
||
|
*
|
||
|
* @param audioSession system wide unique audio session identifier. The HapticGenerator will be
|
||
|
* applied to the players with the same audio session.
|
||
|
* @return HapticGenerator created or null if the device does not support HapticGenerator or
|
||
|
* the audio session is invalid.
|
||
|
* @throws java.lang.IllegalArgumentException when HapticGenerator is not supported
|
||
|
* @throws java.lang.UnsupportedOperationException when the effect library is not loaded.
|
||
|
* @throws java.lang.RuntimeException for all other error
|
||
|
*/
|
||
|
public static @NonNull HapticGenerator create(int audioSession) {
|
||
|
return new HapticGenerator(audioSession);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Class constructor.
|
||
|
*
|
||
|
* @param audioSession system wide unique audio session identifier. The HapticGenerator will be
|
||
|
* attached to the MediaPlayer or AudioTrack in the same audio session.
|
||
|
* @throws java.lang.IllegalArgumentException
|
||
|
* @throws java.lang.UnsupportedOperationException
|
||
|
* @throws java.lang.RuntimeException
|
||
|
*/
|
||
|
private HapticGenerator(int audioSession) {
|
||
|
super(EFFECT_TYPE_HAPTIC_GENERATOR, EFFECT_TYPE_NULL, 0, audioSession);
|
||
|
mVolumeControlEffect = new AudioEffect(
|
||
|
AudioEffect.EFFECT_TYPE_NULL,
|
||
|
UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
|
||
|
0,
|
||
|
audioSession);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enable or disable the effect. The effect can only be enabled if the caller has the
|
||
|
* {@link android.Manifest.permission#VIBRATE} permission.
|
||
|
*
|
||
|
* @param enabled the requested enable state
|
||
|
* @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION}
|
||
|
* or {@link #ERROR_DEAD_OBJECT} in case of failure.
|
||
|
*/
|
||
|
@Override
|
||
|
public int setEnabled(boolean enabled) {
|
||
|
int ret = super.setEnabled(enabled);
|
||
|
if (ret == SUCCESS) {
|
||
|
if (mVolumeControlEffect == null
|
||
|
|| mVolumeControlEffect.setEnabled(enabled) != SUCCESS) {
|
||
|
Log.w(TAG, "Failed to enable volume control effect for HapticGenerator");
|
||
|
}
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Releases the native AudioEffect resources.
|
||
|
*/
|
||
|
@Override
|
||
|
public void release() {
|
||
|
if (mVolumeControlEffect != null) {
|
||
|
mVolumeControlEffect.release();
|
||
|
}
|
||
|
super.release();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Release the resources that are held by the effect.
|
||
|
*/
|
||
|
@Override
|
||
|
public void close() {
|
||
|
release();
|
||
|
}
|
||
|
}
|