Merge "Spatializer: add getter/listener for head tracker availability" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
1a89ec7056
@@ -23548,17 +23548,24 @@ package android.media {
|
||||
}
|
||||
|
||||
public class Spatializer {
|
||||
method public void addOnHeadTrackerAvailableListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnHeadTrackerAvailableListener);
|
||||
method public void addOnSpatializerStateChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnSpatializerStateChangedListener);
|
||||
method public boolean canBeSpatialized(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioFormat);
|
||||
method public int getImmersiveAudioLevel();
|
||||
method public boolean isAvailable();
|
||||
method public boolean isEnabled();
|
||||
method public boolean isHeadTrackerAvailable();
|
||||
method public void removeOnHeadTrackerAvailableListener(@NonNull android.media.Spatializer.OnHeadTrackerAvailableListener);
|
||||
method public void removeOnSpatializerStateChangedListener(@NonNull android.media.Spatializer.OnSpatializerStateChangedListener);
|
||||
field public static final int SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL = 1; // 0x1
|
||||
field public static final int SPATIALIZER_IMMERSIVE_LEVEL_NONE = 0; // 0x0
|
||||
field public static final int SPATIALIZER_IMMERSIVE_LEVEL_OTHER = -1; // 0xffffffff
|
||||
}
|
||||
|
||||
public static interface Spatializer.OnHeadTrackerAvailableListener {
|
||||
method public void onHeadTrackerAvailableChanged(@NonNull android.media.Spatializer, boolean);
|
||||
}
|
||||
|
||||
public static interface Spatializer.OnSpatializerStateChangedListener {
|
||||
method public void onSpatializerAvailableChanged(@NonNull android.media.Spatializer, boolean);
|
||||
method public void onSpatializerEnabledChanged(@NonNull android.media.Spatializer, boolean);
|
||||
|
||||
@@ -39,6 +39,7 @@ import android.media.IRecordingConfigDispatcher;
|
||||
import android.media.IRingtonePlayer;
|
||||
import android.media.IStrategyPreferredDevicesDispatcher;
|
||||
import android.media.ISpatializerCallback;
|
||||
import android.media.ISpatializerHeadTrackerAvailableCallback;
|
||||
import android.media.ISpatializerHeadTrackingModeCallback;
|
||||
import android.media.ISpatializerHeadToSoundStagePoseCallback;
|
||||
import android.media.ISpatializerOutputCallback;
|
||||
@@ -414,6 +415,11 @@ interface IAudioService {
|
||||
|
||||
boolean isHeadTrackerEnabled(in AudioDeviceAttributes device);
|
||||
|
||||
boolean isHeadTrackerAvailable();
|
||||
|
||||
void registerSpatializerHeadTrackerAvailableCallback(
|
||||
in ISpatializerHeadTrackerAvailableCallback cb, boolean register);
|
||||
|
||||
void setSpatializerEnabled(boolean enabled);
|
||||
|
||||
boolean canBeSpatialized(in AudioAttributes aa, in AudioFormat af);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
/**
|
||||
* AIDL for the AudioService to signal whether audio device used by Spatializer has head tracker.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
oneway interface ISpatializerHeadTrackerAvailableCallback {
|
||||
|
||||
void dispatchSpatializerHeadTrackerAvailable(boolean available);
|
||||
}
|
||||
@@ -185,6 +185,45 @@ public class Spatializer {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a head tracker is currently available for the audio device used by the
|
||||
* spatializer effect.
|
||||
* @return true if a head tracker is available and the effect is enabled, false otherwise.
|
||||
* @see OnHeadTrackerAvailableListener
|
||||
* @see #addOnHeadTrackerAvailableListener(Executor, OnHeadTrackerAvailableListener)
|
||||
*/
|
||||
public boolean isHeadTrackerAvailable() {
|
||||
try {
|
||||
return mAm.getService().isHeadTrackerAvailable();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to be notified of changes to the availability of a head tracker.
|
||||
* @param executor the {@code Executor} handling the callback
|
||||
* @param listener the listener to receive availability updates
|
||||
* @see #removeOnHeadTrackerAvailableListener(OnHeadTrackerAvailableListener)
|
||||
*/
|
||||
public void addOnHeadTrackerAvailableListener(@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull OnHeadTrackerAvailableListener listener) {
|
||||
mHeadTrackerListenerMgr.addListener(executor, listener,
|
||||
"addOnHeadTrackerAvailableListener",
|
||||
() -> new SpatializerHeadTrackerAvailableDispatcherStub());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a previously registered listener for the availability of a head tracker.
|
||||
* @param listener the listener previously registered with
|
||||
* {@link #addOnHeadTrackerAvailableListener(Executor, OnHeadTrackerAvailableListener)}
|
||||
*/
|
||||
public void removeOnHeadTrackerAvailableListener(
|
||||
@NonNull OnHeadTrackerAvailableListener listener) {
|
||||
mHeadTrackerListenerMgr.removeListener(listener, "removeOnHeadTrackerAvailableListener");
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = false, value = {
|
||||
SPATIALIZER_IMMERSIVE_LEVEL_OTHER,
|
||||
@@ -401,6 +440,22 @@ public class Spatializer {
|
||||
@HeadTrackingModeSet int mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to be notified of changes to the availability of a head tracker on the audio
|
||||
* device to be used by the spatializer effect.
|
||||
*/
|
||||
public interface OnHeadTrackerAvailableListener {
|
||||
/**
|
||||
* Called when the availability of the head tracker changed.
|
||||
* @param spatializer the {@code Spatializer} instance for which the head tracker
|
||||
* availability was updated
|
||||
* @param available true if the audio device that would output audio processed by
|
||||
* the {@code Spatializer} has a head tracker associated with it, false
|
||||
* otherwise.
|
||||
*/
|
||||
void onHeadTrackerAvailableChanged(@NonNull Spatializer spatializer,
|
||||
boolean available);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
@@ -934,6 +989,36 @@ public class Spatializer {
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// head tracker availability callback management and stub
|
||||
/**
|
||||
* manages the OnHeadTrackerAvailableListener listeners and the
|
||||
* SpatializerHeadTrackerAvailableDispatcherStub
|
||||
*/
|
||||
private final CallbackUtil.LazyListenerManager<OnHeadTrackerAvailableListener>
|
||||
mHeadTrackerListenerMgr = new CallbackUtil.LazyListenerManager();
|
||||
|
||||
private final class SpatializerHeadTrackerAvailableDispatcherStub
|
||||
extends ISpatializerHeadTrackerAvailableCallback.Stub
|
||||
implements CallbackUtil.DispatcherStub {
|
||||
@Override
|
||||
public void register(boolean register) {
|
||||
try {
|
||||
mAm.getService().registerSpatializerHeadTrackerAvailableCallback(this, register);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("GuardedBy") // lock applied inside callListeners method
|
||||
public void dispatchSpatializerHeadTrackerAvailable(boolean available) {
|
||||
mHeadTrackerListenerMgr.callListeners(
|
||||
(listener) -> listener.onHeadTrackerAvailableChanged(
|
||||
Spatializer.this, available));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// head pose callback management and stub
|
||||
private final Object mPoseListenerLock = new Object();
|
||||
|
||||
@@ -102,6 +102,7 @@ import android.media.IRecordingConfigDispatcher;
|
||||
import android.media.IRingtonePlayer;
|
||||
import android.media.ISpatializerCallback;
|
||||
import android.media.ISpatializerHeadToSoundStagePoseCallback;
|
||||
import android.media.ISpatializerHeadTrackerAvailableCallback;
|
||||
import android.media.ISpatializerHeadTrackingModeCallback;
|
||||
import android.media.ISpatializerOutputCallback;
|
||||
import android.media.IStrategyPreferredDevicesDispatcher;
|
||||
@@ -8723,6 +8724,11 @@ public class AudioService extends IAudioService.Stub
|
||||
return mSpatializerHelper.isHeadTrackerEnabled(Objects.requireNonNull(device));
|
||||
}
|
||||
|
||||
/** @see Spatializer#isHeadTrackerAvailable() */
|
||||
public boolean isHeadTrackerAvailable() {
|
||||
return mSpatializerHelper.isHeadTrackerAvailable();
|
||||
}
|
||||
|
||||
/** @see Spatializer#setSpatializerEnabled(boolean) */
|
||||
public void setSpatializerEnabled(boolean enabled) {
|
||||
enforceModifyDefaultAudioEffectsPermission();
|
||||
@@ -8767,6 +8773,13 @@ public class AudioService extends IAudioService.Stub
|
||||
mSpatializerHelper.unregisterHeadTrackingModeCallback(cb);
|
||||
}
|
||||
|
||||
/** @see Spatializer.SpatializerHeadTrackerAvailableDispatcherStub */
|
||||
public void registerSpatializerHeadTrackerAvailableCallback(
|
||||
@NonNull ISpatializerHeadTrackerAvailableCallback cb, boolean register) {
|
||||
Objects.requireNonNull(cb);
|
||||
mSpatializerHelper.registerHeadTrackerAvailableCallback(cb, register);
|
||||
}
|
||||
|
||||
/** @see Spatializer#setOnHeadToSoundstagePoseUpdatedListener */
|
||||
public void registerHeadToSoundstagePoseCallback(
|
||||
@NonNull ISpatializerHeadToSoundStagePoseCallback cb) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.media.INativeSpatializerCallback;
|
||||
import android.media.ISpatializer;
|
||||
import android.media.ISpatializerCallback;
|
||||
import android.media.ISpatializerHeadToSoundStagePoseCallback;
|
||||
import android.media.ISpatializerHeadTrackerAvailableCallback;
|
||||
import android.media.ISpatializerHeadTrackingCallback;
|
||||
import android.media.ISpatializerHeadTrackingModeCallback;
|
||||
import android.media.ISpatializerOutputCallback;
|
||||
@@ -126,6 +127,7 @@ public class SpatializerHelper {
|
||||
private boolean mBinauralSupported = false;
|
||||
private int mActualHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_UNSUPPORTED;
|
||||
private int mDesiredHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD;
|
||||
private boolean mHeadTrackerAvailable = false;
|
||||
/**
|
||||
* The desired head tracking mode when enabling head tracking, tracks mDesiredHeadTrackingMode,
|
||||
* except when head tracking gets disabled through setting the desired mode to
|
||||
@@ -831,6 +833,7 @@ public class SpatializerHelper {
|
||||
mSpatCallback = null;
|
||||
try {
|
||||
mSpat.registerHeadTrackingCallback(null);
|
||||
mHeadTrackerAvailable = false;
|
||||
mSpat.release();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Can't set release spatializer cleanly", e);
|
||||
@@ -890,6 +893,18 @@ public class SpatializerHelper {
|
||||
mHeadTrackingModeCallbacks.unregister(callback);
|
||||
}
|
||||
|
||||
final RemoteCallbackList<ISpatializerHeadTrackerAvailableCallback> mHeadTrackerCallbacks =
|
||||
new RemoteCallbackList<>();
|
||||
|
||||
synchronized void registerHeadTrackerAvailableCallback(
|
||||
@NonNull ISpatializerHeadTrackerAvailableCallback cb, boolean register) {
|
||||
if (register) {
|
||||
mHeadTrackerCallbacks.register(cb);
|
||||
} else {
|
||||
mHeadTrackerCallbacks.unregister(cb);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized int[] getSupportedHeadTrackingModes() {
|
||||
switch (mState) {
|
||||
case STATE_UNINITIALIZED:
|
||||
@@ -1090,6 +1105,10 @@ public class SpatializerHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized boolean isHeadTrackerAvailable() {
|
||||
return mHeadTrackerAvailable;
|
||||
}
|
||||
|
||||
private boolean checkSpatForHeadTracking(String funcName) {
|
||||
switch (mState) {
|
||||
case STATE_UNINITIALIZED:
|
||||
@@ -1115,7 +1134,8 @@ public class SpatializerHelper {
|
||||
mHeadTrackingModeCallbacks.getBroadcastItem(i)
|
||||
.dispatchSpatializerActualHeadTrackingModeChanged(newMode);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in dispatchSpatializerActualHeadTrackingModeChanged", e);
|
||||
Log.e(TAG, "Error in dispatchSpatializerActualHeadTrackingModeChanged("
|
||||
+ newMode + ")", e);
|
||||
}
|
||||
}
|
||||
mHeadTrackingModeCallbacks.finishBroadcast();
|
||||
@@ -1128,12 +1148,27 @@ public class SpatializerHelper {
|
||||
mHeadTrackingModeCallbacks.getBroadcastItem(i)
|
||||
.dispatchSpatializerDesiredHeadTrackingModeChanged(newMode);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in dispatchSpatializerDesiredHeadTrackingModeChanged", e);
|
||||
Log.e(TAG, "Error in dispatchSpatializerDesiredHeadTrackingModeChanged("
|
||||
+ newMode + ")", e);
|
||||
}
|
||||
}
|
||||
mHeadTrackingModeCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
private void dispatchHeadTrackerAvailable(boolean available) {
|
||||
final int nbCallbacks = mHeadTrackerCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < nbCallbacks; i++) {
|
||||
try {
|
||||
mHeadTrackerCallbacks.getBroadcastItem(i)
|
||||
.dispatchSpatializerHeadTrackerAvailable(available);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error in dispatchSpatializerHeadTrackerAvailable("
|
||||
+ available + ")", e);
|
||||
}
|
||||
}
|
||||
mHeadTrackerCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// head pose
|
||||
final RemoteCallbackList<ISpatializerHeadToSoundStagePoseCallback> mHeadPoseCallbacks =
|
||||
@@ -1348,6 +1383,10 @@ public class SpatializerHelper {
|
||||
try {
|
||||
Log.i(TAG, "setHeadSensor:" + headHandle);
|
||||
mSpat.setHeadSensor(headHandle);
|
||||
if (mHeadTrackerAvailable != (headHandle != -1)) {
|
||||
mHeadTrackerAvailable = (headHandle != -1);
|
||||
dispatchHeadTrackerAvailable(mHeadTrackerAvailable);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error calling setHeadSensor:" + headHandle, e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user