Loading media/java/android/media/Spatializer.java +8 −0 Original line number Diff line number Diff line Loading @@ -129,6 +129,14 @@ public class Spatializer { */ public static final int SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL = 1; /** * @hide * Constant indicating the {@code Spatializer} on this device supports the spatialization of * multichannel bed plus objects. * @see #getImmersiveAudioLevel() */ public static final int SPATIALIZER_IMMERSIVE_LEVEL_MCHAN_BED_PLUS_OBJECTS = 2; /** @hide */ @IntDef(flag = false, value = { HEAD_TRACKING_MODE_UNSUPPORTED, Loading services/core/java/com/android/server/audio/AudioService.java +18 −1 Original line number Diff line number Diff line Loading @@ -243,7 +243,7 @@ public class AudioService extends IAudioService.Stub */ private static final int FLAG_ADJUST_VOLUME = 1; private final Context mContext; final Context mContext; private final ContentResolver mContentResolver; private final AppOpsManager mAppOps; Loading Loading @@ -318,6 +318,7 @@ public class AudioService extends IAudioService.Stub private static final int MSG_A2DP_DEV_CONFIG_CHANGE = 39; private static final int MSG_DISPATCH_AUDIO_MODE = 40; private static final int MSG_ROUTING_UPDATED = 41; private static final int MSG_INIT_HEADTRACKING_SENSORS = 42; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), Loading Loading @@ -7575,6 +7576,10 @@ public class AudioService extends IAudioService.Stub mAudioEventWakeLock.release(); break; case MSG_INIT_HEADTRACKING_SENSORS: mSpatializerHelper.onInitSensors(/*init*/ msg.arg1 == 1); break; case MSG_CHECK_MUSIC_ACTIVE: onCheckMusicActive((String) msg.obj); break; Loading Loading @@ -8447,6 +8452,18 @@ public class AudioService extends IAudioService.Stub mSpatializerHelper.getEffectParameter(key, value); } /** * post a message to schedule init/release of head tracking sensors * @param init initialization if true, release if false */ void postInitSpatializerHeadTrackingSensors(boolean init) { sendMsg(mAudioHandler, MSG_INIT_HEADTRACKING_SENSORS, SENDMSG_REPLACE, /*arg1*/ init ? 1 : 0, 0, TAG, /*delay*/ 0); } //========================================================================================== private boolean readCameraSoundForced() { return SystemProperties.getBoolean("audio.camerasound.force", false) || Loading services/core/java/com/android/server/audio/SpatializerHelper.java +113 −33 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ package com.android.server.audio; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorManager; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioFormat; Loading @@ -28,6 +31,7 @@ import android.media.ISpatializerCallback; import android.media.ISpatializerHeadToSoundStagePoseCallback; import android.media.ISpatializerHeadTrackingCallback; import android.media.ISpatializerHeadTrackingModeCallback; import android.media.SpatializationLevel; import android.media.Spatializer; import android.media.SpatializerHeadTrackingMode; import android.os.RemoteCallbackList; Loading @@ -45,6 +49,7 @@ public class SpatializerHelper { private static final String TAG = "AS.SpatializerHelper"; private static final boolean DEBUG = true; private static final boolean DEBUG_MORE = false; private static void logd(String s) { if (DEBUG) { Loading @@ -54,6 +59,7 @@ public class SpatializerHelper { private final @NonNull AudioSystemAdapter mASA; private final @NonNull AudioService mAudioService; private @Nullable SensorManager mSensorManager; //------------------------------------------------------------ // Spatializer state machine Loading Loading @@ -127,7 +133,7 @@ public class SpatializerHelper { for (byte level : levels) { logd("found support for level: " + level); if (level == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL) { logd("Setting Spatializer to LEVEL_MULTICHANNEL"); logd("Setting capable level to LEVEL_MULTICHANNEL"); mCapableSpatLevel = level; break; } Loading Loading @@ -191,9 +197,16 @@ public class SpatializerHelper { public void onLevelChanged(byte level) { logd("SpatializerCallback.onLevelChanged level:" + level); synchronized (SpatializerHelper.this) { mSpatLevel = level; mSpatLevel = spatializationLevelToSpatializerInt(level); } // TODO use reported spat level to change state // init sensors if (level == SpatializationLevel.NONE) { initSensors(/*init*/false); } else { postInitSensors(true); } } }; Loading Loading @@ -224,7 +237,7 @@ public class SpatializerHelper { + " invalid transform length" + headToStage.length); return; } if (DEBUG) { if (DEBUG_MORE) { // 6 values * (4 digits + 1 dot + 2 brackets) = 42 characters StringBuilder t = new StringBuilder(42); for (float val : headToStage) { Loading Loading @@ -641,36 +654,6 @@ public class SpatializerHelper { } } private int headTrackingModeTypeToSpatializerInt(byte mode) { switch (mode) { case SpatializerHeadTrackingMode.OTHER: return Spatializer.HEAD_TRACKING_MODE_OTHER; case SpatializerHeadTrackingMode.DISABLED: return Spatializer.HEAD_TRACKING_MODE_DISABLED; case SpatializerHeadTrackingMode.RELATIVE_WORLD: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD; case SpatializerHeadTrackingMode.RELATIVE_SCREEN: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE; default: throw(new IllegalArgumentException("Unexpected head tracking mode:" + mode)); } } private byte spatializerIntToHeadTrackingModeType(int sdkMode) { switch (sdkMode) { case Spatializer.HEAD_TRACKING_MODE_OTHER: return SpatializerHeadTrackingMode.OTHER; case Spatializer.HEAD_TRACKING_MODE_DISABLED: return SpatializerHeadTrackingMode.DISABLED; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD: return SpatializerHeadTrackingMode.RELATIVE_WORLD; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE: return SpatializerHeadTrackingMode.RELATIVE_SCREEN; default: throw(new IllegalArgumentException("Unexpected head tracking mode:" + sdkMode)); } } private boolean checkSpatForHeadTracking(String funcName) { switch (mState) { case STATE_UNINITIALIZED: Loading Loading @@ -792,4 +775,101 @@ public class SpatializerHelper { Log.e(TAG, "Error in getParameter for key:" + key, e); } } //------------------------------------------------------ // sensors private void initSensors(boolean init) { if (mSensorManager == null) { mSensorManager = (SensorManager) mAudioService.mContext.getSystemService(Context.SENSOR_SERVICE); } final int headHandle; final int screenHandle; if (init) { if (mSensorManager == null) { Log.e(TAG, "Null SensorManager, can't init sensors"); return; } // TODO replace with dynamic association of sensor for headtracker Sensor headSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR); headHandle = headSensor.getHandle(); //Sensor screenSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); //screenHandle = deviceSensor.getHandle(); screenHandle = -1; } else { // -1 is disable value screenHandle = -1; headHandle = -1; } try { Log.i(TAG, "setScreenSensor:" + screenHandle); mSpat.setScreenSensor(screenHandle); } catch (Exception e) { Log.e(TAG, "Error calling setScreenSensor:" + screenHandle, e); } try { Log.i(TAG, "setHeadSensor:" + headHandle); mSpat.setHeadSensor(headHandle); } catch (Exception e) { Log.e(TAG, "Error calling setHeadSensor:" + headHandle, e); } } private void postInitSensors(boolean init) { mAudioService.postInitSpatializerHeadTrackingSensors(init); } synchronized void onInitSensors(boolean init) { final int[] modes = getSupportedHeadTrackingModes(); if (modes.length == 0) { Log.i(TAG, "not initializing sensors, no headtracking supported"); return; } initSensors(init); } //------------------------------------------------------ // SDK <-> AIDL converters private static int headTrackingModeTypeToSpatializerInt(byte mode) { switch (mode) { case SpatializerHeadTrackingMode.OTHER: return Spatializer.HEAD_TRACKING_MODE_OTHER; case SpatializerHeadTrackingMode.DISABLED: return Spatializer.HEAD_TRACKING_MODE_DISABLED; case SpatializerHeadTrackingMode.RELATIVE_WORLD: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD; case SpatializerHeadTrackingMode.RELATIVE_SCREEN: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE; default: throw(new IllegalArgumentException("Unexpected head tracking mode:" + mode)); } } private static byte spatializerIntToHeadTrackingModeType(int sdkMode) { switch (sdkMode) { case Spatializer.HEAD_TRACKING_MODE_OTHER: return SpatializerHeadTrackingMode.OTHER; case Spatializer.HEAD_TRACKING_MODE_DISABLED: return SpatializerHeadTrackingMode.DISABLED; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD: return SpatializerHeadTrackingMode.RELATIVE_WORLD; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE: return SpatializerHeadTrackingMode.RELATIVE_SCREEN; default: throw(new IllegalArgumentException("Unexpected head tracking mode:" + sdkMode)); } } private static int spatializationLevelToSpatializerInt(byte level) { switch (level) { case SpatializationLevel.NONE: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; case SpatializationLevel.SPATIALIZER_MULTICHANNEL: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL; case SpatializationLevel.SPATIALIZER_MCHAN_BED_PLUS_OBJECTS: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MCHAN_BED_PLUS_OBJECTS; default: throw(new IllegalArgumentException("Unexpected spatializer level:" + level)); } } } Loading
media/java/android/media/Spatializer.java +8 −0 Original line number Diff line number Diff line Loading @@ -129,6 +129,14 @@ public class Spatializer { */ public static final int SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL = 1; /** * @hide * Constant indicating the {@code Spatializer} on this device supports the spatialization of * multichannel bed plus objects. * @see #getImmersiveAudioLevel() */ public static final int SPATIALIZER_IMMERSIVE_LEVEL_MCHAN_BED_PLUS_OBJECTS = 2; /** @hide */ @IntDef(flag = false, value = { HEAD_TRACKING_MODE_UNSUPPORTED, Loading
services/core/java/com/android/server/audio/AudioService.java +18 −1 Original line number Diff line number Diff line Loading @@ -243,7 +243,7 @@ public class AudioService extends IAudioService.Stub */ private static final int FLAG_ADJUST_VOLUME = 1; private final Context mContext; final Context mContext; private final ContentResolver mContentResolver; private final AppOpsManager mAppOps; Loading Loading @@ -318,6 +318,7 @@ public class AudioService extends IAudioService.Stub private static final int MSG_A2DP_DEV_CONFIG_CHANGE = 39; private static final int MSG_DISPATCH_AUDIO_MODE = 40; private static final int MSG_ROUTING_UPDATED = 41; private static final int MSG_INIT_HEADTRACKING_SENSORS = 42; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), Loading Loading @@ -7575,6 +7576,10 @@ public class AudioService extends IAudioService.Stub mAudioEventWakeLock.release(); break; case MSG_INIT_HEADTRACKING_SENSORS: mSpatializerHelper.onInitSensors(/*init*/ msg.arg1 == 1); break; case MSG_CHECK_MUSIC_ACTIVE: onCheckMusicActive((String) msg.obj); break; Loading Loading @@ -8447,6 +8452,18 @@ public class AudioService extends IAudioService.Stub mSpatializerHelper.getEffectParameter(key, value); } /** * post a message to schedule init/release of head tracking sensors * @param init initialization if true, release if false */ void postInitSpatializerHeadTrackingSensors(boolean init) { sendMsg(mAudioHandler, MSG_INIT_HEADTRACKING_SENSORS, SENDMSG_REPLACE, /*arg1*/ init ? 1 : 0, 0, TAG, /*delay*/ 0); } //========================================================================================== private boolean readCameraSoundForced() { return SystemProperties.getBoolean("audio.camerasound.force", false) || Loading
services/core/java/com/android/server/audio/SpatializerHelper.java +113 −33 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ package com.android.server.audio; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorManager; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioFormat; Loading @@ -28,6 +31,7 @@ import android.media.ISpatializerCallback; import android.media.ISpatializerHeadToSoundStagePoseCallback; import android.media.ISpatializerHeadTrackingCallback; import android.media.ISpatializerHeadTrackingModeCallback; import android.media.SpatializationLevel; import android.media.Spatializer; import android.media.SpatializerHeadTrackingMode; import android.os.RemoteCallbackList; Loading @@ -45,6 +49,7 @@ public class SpatializerHelper { private static final String TAG = "AS.SpatializerHelper"; private static final boolean DEBUG = true; private static final boolean DEBUG_MORE = false; private static void logd(String s) { if (DEBUG) { Loading @@ -54,6 +59,7 @@ public class SpatializerHelper { private final @NonNull AudioSystemAdapter mASA; private final @NonNull AudioService mAudioService; private @Nullable SensorManager mSensorManager; //------------------------------------------------------------ // Spatializer state machine Loading Loading @@ -127,7 +133,7 @@ public class SpatializerHelper { for (byte level : levels) { logd("found support for level: " + level); if (level == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL) { logd("Setting Spatializer to LEVEL_MULTICHANNEL"); logd("Setting capable level to LEVEL_MULTICHANNEL"); mCapableSpatLevel = level; break; } Loading Loading @@ -191,9 +197,16 @@ public class SpatializerHelper { public void onLevelChanged(byte level) { logd("SpatializerCallback.onLevelChanged level:" + level); synchronized (SpatializerHelper.this) { mSpatLevel = level; mSpatLevel = spatializationLevelToSpatializerInt(level); } // TODO use reported spat level to change state // init sensors if (level == SpatializationLevel.NONE) { initSensors(/*init*/false); } else { postInitSensors(true); } } }; Loading Loading @@ -224,7 +237,7 @@ public class SpatializerHelper { + " invalid transform length" + headToStage.length); return; } if (DEBUG) { if (DEBUG_MORE) { // 6 values * (4 digits + 1 dot + 2 brackets) = 42 characters StringBuilder t = new StringBuilder(42); for (float val : headToStage) { Loading Loading @@ -641,36 +654,6 @@ public class SpatializerHelper { } } private int headTrackingModeTypeToSpatializerInt(byte mode) { switch (mode) { case SpatializerHeadTrackingMode.OTHER: return Spatializer.HEAD_TRACKING_MODE_OTHER; case SpatializerHeadTrackingMode.DISABLED: return Spatializer.HEAD_TRACKING_MODE_DISABLED; case SpatializerHeadTrackingMode.RELATIVE_WORLD: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD; case SpatializerHeadTrackingMode.RELATIVE_SCREEN: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE; default: throw(new IllegalArgumentException("Unexpected head tracking mode:" + mode)); } } private byte spatializerIntToHeadTrackingModeType(int sdkMode) { switch (sdkMode) { case Spatializer.HEAD_TRACKING_MODE_OTHER: return SpatializerHeadTrackingMode.OTHER; case Spatializer.HEAD_TRACKING_MODE_DISABLED: return SpatializerHeadTrackingMode.DISABLED; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD: return SpatializerHeadTrackingMode.RELATIVE_WORLD; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE: return SpatializerHeadTrackingMode.RELATIVE_SCREEN; default: throw(new IllegalArgumentException("Unexpected head tracking mode:" + sdkMode)); } } private boolean checkSpatForHeadTracking(String funcName) { switch (mState) { case STATE_UNINITIALIZED: Loading Loading @@ -792,4 +775,101 @@ public class SpatializerHelper { Log.e(TAG, "Error in getParameter for key:" + key, e); } } //------------------------------------------------------ // sensors private void initSensors(boolean init) { if (mSensorManager == null) { mSensorManager = (SensorManager) mAudioService.mContext.getSystemService(Context.SENSOR_SERVICE); } final int headHandle; final int screenHandle; if (init) { if (mSensorManager == null) { Log.e(TAG, "Null SensorManager, can't init sensors"); return; } // TODO replace with dynamic association of sensor for headtracker Sensor headSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR); headHandle = headSensor.getHandle(); //Sensor screenSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); //screenHandle = deviceSensor.getHandle(); screenHandle = -1; } else { // -1 is disable value screenHandle = -1; headHandle = -1; } try { Log.i(TAG, "setScreenSensor:" + screenHandle); mSpat.setScreenSensor(screenHandle); } catch (Exception e) { Log.e(TAG, "Error calling setScreenSensor:" + screenHandle, e); } try { Log.i(TAG, "setHeadSensor:" + headHandle); mSpat.setHeadSensor(headHandle); } catch (Exception e) { Log.e(TAG, "Error calling setHeadSensor:" + headHandle, e); } } private void postInitSensors(boolean init) { mAudioService.postInitSpatializerHeadTrackingSensors(init); } synchronized void onInitSensors(boolean init) { final int[] modes = getSupportedHeadTrackingModes(); if (modes.length == 0) { Log.i(TAG, "not initializing sensors, no headtracking supported"); return; } initSensors(init); } //------------------------------------------------------ // SDK <-> AIDL converters private static int headTrackingModeTypeToSpatializerInt(byte mode) { switch (mode) { case SpatializerHeadTrackingMode.OTHER: return Spatializer.HEAD_TRACKING_MODE_OTHER; case SpatializerHeadTrackingMode.DISABLED: return Spatializer.HEAD_TRACKING_MODE_DISABLED; case SpatializerHeadTrackingMode.RELATIVE_WORLD: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD; case SpatializerHeadTrackingMode.RELATIVE_SCREEN: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE; default: throw(new IllegalArgumentException("Unexpected head tracking mode:" + mode)); } } private static byte spatializerIntToHeadTrackingModeType(int sdkMode) { switch (sdkMode) { case Spatializer.HEAD_TRACKING_MODE_OTHER: return SpatializerHeadTrackingMode.OTHER; case Spatializer.HEAD_TRACKING_MODE_DISABLED: return SpatializerHeadTrackingMode.DISABLED; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD: return SpatializerHeadTrackingMode.RELATIVE_WORLD; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE: return SpatializerHeadTrackingMode.RELATIVE_SCREEN; default: throw(new IllegalArgumentException("Unexpected head tracking mode:" + sdkMode)); } } private static int spatializationLevelToSpatializerInt(byte level) { switch (level) { case SpatializationLevel.NONE: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; case SpatializationLevel.SPATIALIZER_MULTICHANNEL: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL; case SpatializationLevel.SPATIALIZER_MCHAN_BED_PLUS_OBJECTS: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MCHAN_BED_PLUS_OBJECTS; default: throw(new IllegalArgumentException("Unexpected spatializer level:" + level)); } } }