Spatial audio: read prop for spatializer init, persist feature state
Use property ro.audio.spatializer_enabled to optimize the
AudioService initialization of Spatializer.
Persist the state of the spatial audo feature whenever its state
changes. Read it at start or whenever AudioService needs to
re-initialize the feature (after audio_server restart)
Bug: 188502620
Test: adb shell dumpsys audio | grep -A 4 Spatial
Change-Id: I667ff7f0247396aad698765455e400337d9c6dcb
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0899ef5..1bdfdc2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8966,6 +8966,15 @@
public static final String UNSAFE_VOLUME_MUSIC_ACTIVE_MS = "unsafe_volume_music_active_ms";
/**
+ * Indicates whether the spatial audio feature was enabled for this user.
+ *
+ * Type : int (0 disabled, 1 enabled)
+ *
+ * @hide
+ */
+ public static final String SPATIAL_AUDIO_ENABLED = "spatial_audio_enabled";
+
+ /**
* Indicates whether notification display on the lock screen is enabled.
* <p>
* Type: int (0 for false, 1 for true)
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 246cf25..8c19284 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -319,6 +319,7 @@
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;
+ private static final int MSG_PERSIST_SPATIAL_AUDIO_ENABLED = 43;
// start of messages handled under wakelock
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
@@ -1038,12 +1039,13 @@
mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
+ mHasSpatializerEffect = SystemProperties.getBoolean("ro.audio.spatializer_enabled", false);
+
// done with service initialization, continue additional work in our Handler thread
queueMsgUnderWakeLock(mAudioHandler, MSG_INIT_STREAMS_VOLUMES,
0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
queueMsgUnderWakeLock(mAudioHandler, MSG_INIT_SPATIALIZER,
- 0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
-
+ 0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
}
/**
@@ -1237,6 +1239,9 @@
// routing monitoring from AudioSystemAdapter
@Override
public void onRoutingUpdatedFromNative() {
+ if (!mHasSpatializerEffect) {
+ return;
+ }
sendMsg(mAudioHandler,
MSG_ROUTING_UPDATED,
SENDMSG_REPLACE, 0, 0, null,
@@ -1433,8 +1438,10 @@
}
}
- // TODO check property if feature enabled
- mSpatializerHelper.reset(/* featureEnabled */ SPATIALIZER_FEATURE_ENABLED_DEFAULT);
+ if (mHasSpatializerEffect) {
+ mSpatializerHelper.reset(/* featureEnabled */ isSpatialAudioEnabled());
+ monitorRoutingChanges(true);
+ }
onIndicateSystemReady();
// indicate the end of reconfiguration phase to audio HAL
@@ -7570,9 +7577,11 @@
break;
case MSG_INIT_SPATIALIZER:
- mSpatializerHelper.init();
- // TODO read property to see if enabled
- mSpatializerHelper.setFeatureEnabled(SPATIALIZER_FEATURE_ENABLED_DEFAULT);
+ mSpatializerHelper.init(/*effectExpected*/ mHasSpatializerEffect);
+ if (mHasSpatializerEffect) {
+ mSpatializerHelper.setFeatureEnabled(isSpatialAudioEnabled());
+ monitorRoutingChanges(true);
+ }
mAudioEventWakeLock.release();
break;
@@ -7716,6 +7725,10 @@
case MSG_ROUTING_UPDATED:
mSpatializerHelper.onRoutingUpdated();
break;
+
+ case MSG_PERSIST_SPATIAL_AUDIO_ENABLED:
+ onPersistSpatialAudioEnabled(msg.arg1 == 1);
+ break;
}
}
}
@@ -8285,7 +8298,40 @@
//==========================================================================================
private final @NonNull SpatializerHelper mSpatializerHelper;
- private static final boolean SPATIALIZER_FEATURE_ENABLED_DEFAULT = false;
+ /**
+ * Initialized from property ro.audio.spatializer_enabled
+ * Should only be 1 when the device ships with a Spatializer effect
+ */
+ private final boolean mHasSpatializerEffect;
+ /**
+ * Default value for the spatial audio feature
+ */
+ private static final boolean SPATIAL_AUDIO_ENABLED_DEFAULT = true;
+
+ /**
+ * persist in user settings whether the feature is enabled.
+ * Can change when {@link Spatializer#setEnabled(boolean)} is called and successfully
+ * changes the state of the feature
+ * @param featureEnabled
+ */
+ void persistSpatialAudioEnabled(boolean featureEnabled) {
+ sendMsg(mAudioHandler,
+ MSG_PERSIST_SPATIAL_AUDIO_ENABLED,
+ SENDMSG_REPLACE, featureEnabled ? 1 : 0, 0, null,
+ /*delay ms*/ 100);
+ }
+
+ void onPersistSpatialAudioEnabled(boolean enabled) {
+ Settings.Secure.putIntForUser(mContentResolver,
+ Settings.Secure.SPATIAL_AUDIO_ENABLED, enabled ? 1 : 0,
+ UserHandle.USER_CURRENT);
+ }
+
+ boolean isSpatialAudioEnabled() {
+ return Settings.Secure.getIntForUser(mContentResolver,
+ Settings.Secure.SPATIAL_AUDIO_ENABLED, SPATIAL_AUDIO_ENABLED_DEFAULT ? 1 : 0,
+ UserHandle.USER_CURRENT) == 1;
+ }
private void enforceModifyDefaultAudioEffectsPermission() {
if (mContext.checkCallingOrSelfPermission(
@@ -9044,6 +9090,12 @@
sVolumeLogger.dump(pw);
pw.println("\n");
dumpSupportedSystemUsage(pw);
+
+ pw.println("\n");
+ pw.println("\nSpatial audio:");
+ pw.println("mHasSpatializerEffect:" + mHasSpatializerEffect);
+ pw.println("isSpatializerEnabled:" + isSpatializerEnabled());
+ pw.println("isSpatialAudioEnabled:" + isSpatialAudioEnabled());
}
private void dumpSupportedSystemUsage(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 66afe9b..b2fa86b 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -106,8 +106,13 @@
mASA = asa;
}
- synchronized void init() {
+ synchronized void init(boolean effectExpected) {
Log.i(TAG, "Initializing");
+ if (!effectExpected) {
+ Log.i(TAG, "Setting state to STATE_NOT_SUPPORTED due to effect not expected");
+ mState = STATE_NOT_SUPPORTED;
+ return;
+ }
if (mState != STATE_UNINITIALIZED) {
throw new IllegalStateException(("init() called in state:" + mState));
}
@@ -165,7 +170,7 @@
mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
mActualHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_UNSUPPORTED;
- init();
+ init(true);
setFeatureEnabled(featureEnabled);
}
@@ -391,7 +396,7 @@
}
}
mStateCallbacks.finishBroadcast();
- // TODO persist enabled state
+ mAudioService.persistSpatialAudioEnabled(featureEnabled);
}
private synchronized void setDispatchAvailableState(boolean available) {