Spatializer: Add head tracking callback

Split head tracking related events from main INativeSpatializerCallback
to a dedicated callback ISpatializerHeadTrackingCallback that can
be registerred and unregistered independently.

Bug: 188502620
Test: manual test with mock spatializer
Change-Id: I09eefb0911f557a6faa6cf0b6c1afe7eaf71ca84
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index fbbd7ff..3c3d340 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -502,6 +502,7 @@
     srcs: [
         "aidl/android/media/INativeSpatializerCallback.aidl",
         "aidl/android/media/ISpatializer.aidl",
+        "aidl/android/media/ISpatializerHeadTrackingCallback.aidl",
     ],
     imports: [
         "audiopolicy-types-aidl",
diff --git a/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl b/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
index 73e897d..0e9634c 100644
--- a/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
+++ b/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
@@ -31,15 +31,4 @@
      * (e.g. when the spatializer is enabled or disabled)
      */
     void onLevelChanged(SpatializationLevel level);
-
-    /** Called when the head tracking mode has changed
-     */
-    void onHeadTrackingModeChanged(SpatializerHeadTrackingMode mode);
-
-    /** Called when the head to stage pose hase been updated
-     * The head to stage pose is conveyed as a vector of 6 elements,
-     * where the first three are a translation vector and
-     * the last three are a rotation vector.
-     */
-    void onHeadToSoundStagePoseUpdated(in float[] headToStage);
 }
diff --git a/media/libaudioclient/aidl/android/media/ISpatializer.aidl b/media/libaudioclient/aidl/android/media/ISpatializer.aidl
index e5bf50c..72e8b2e 100644
--- a/media/libaudioclient/aidl/android/media/ISpatializer.aidl
+++ b/media/libaudioclient/aidl/android/media/ISpatializer.aidl
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.media.ISpatializerHeadTrackingCallback;
 import android.media.SpatializationLevel;
 import android.media.SpatializationMode;
 import android.media.SpatializerHeadTrackingMode;
@@ -103,4 +104,13 @@
      * retrieved with IAudioPolicyService.getSpatializer().
      */
     SpatializationMode[] getSupportedModes();
+
+    /**
+     * Registers a callback to monitor head tracking functions.
+     * Only one callback can be registered on a Spatializer.
+     * The last callback registered wins and passing a nullptr unregisters
+     * last registered callback.
+     */
+    void registerHeadTrackingCallback(ISpatializerHeadTrackingCallback callback);
+
 }
diff --git a/media/libaudioclient/aidl/android/media/ISpatializerHeadTrackingCallback.aidl b/media/libaudioclient/aidl/android/media/ISpatializerHeadTrackingCallback.aidl
new file mode 100644
index 0000000..23d5e13
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/ISpatializerHeadTrackingCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 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;
+
+import android.media.SpatializationLevel;
+import android.media.SpatializerHeadTrackingMode;
+
+/**
+ * The ISpatializerHeadTrackingCallback interface is a callback associated to the
+ * Spatializer head tracking function. It can be registered via the ISpatializer
+ * interface to monitor head tracking related states.
+ * {@hide}
+ */
+oneway interface ISpatializerHeadTrackingCallback {
+    /** Called when the head tracking mode has changed
+     */
+    void onHeadTrackingModeChanged(SpatializerHeadTrackingMode mode);
+
+    /** Called when the head to stage pose hase been updated
+     * The head to stage pose is conveyed as a vector of 6 elements,
+     * where the first three are a translation vector and
+     * the last three are a rotation vector.
+     */
+    void onHeadToSoundStagePoseUpdated(in float[] headToStage);
+}
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index ee25dc8..161c61e 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -506,6 +506,17 @@
     return Status::ok();
 }
 
+Status Spatializer::registerHeadTrackingCallback(
+        const sp<media::ISpatializerHeadTrackingCallback>& callback) {
+    ALOGV("%s callback %p", __func__, callback.get());
+    std::lock_guard lock(mLock);
+    if (!mSupportsHeadTracking) {
+        return binderStatusFromStatusT(INVALID_OPERATION);
+    }
+    mHeadTrackingCallback = callback;
+    return Status::ok();
+}
+
 // SpatializerPoseController::Listener
 void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
     ALOGV("%s", __func__);
@@ -526,10 +537,10 @@
 
 void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
     ALOGV("%s", __func__);
-    sp<media::INativeSpatializerCallback> callback;
+    sp<media::ISpatializerHeadTrackingCallback> callback;
     {
         std::lock_guard lock(mLock);
-        callback = mSpatializerCallback;
+        callback = mHeadTrackingCallback;
         if (mEngine != nullptr) {
             setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
         }
@@ -550,7 +561,7 @@
 
 void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
     ALOGV("%s(%d)", __func__, (int) mode);
-    sp<media::INativeSpatializerCallback> callback;
+    sp<media::ISpatializerHeadTrackingCallback> callback;
     SpatializerHeadTrackingMode spatializerMode;
     {
         std::lock_guard lock(mLock);
@@ -572,7 +583,7 @@
             }
         }
         mActualHeadTrackingMode = spatializerMode;
-        callback = mSpatializerCallback;
+        callback = mHeadTrackingCallback;
     }
     if (callback != nullptr) {
         callback->onHeadTrackingModeChanged(spatializerMode);
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index ae7ded8..7a18cbe 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -113,7 +113,8 @@
     binder::Status setDisplayOrientation(float physicalToLogicalAngle) override;
     binder::Status setHingeAngle(float hingeAngle) override;
     binder::Status getSupportedModes(std::vector<media::SpatializationMode>* modes) override;
-
+    binder::Status registerHeadTrackingCallback(
+        const sp<media::ISpatializerHeadTrackingCallback>& callback) override;
 
     /** IBinder::DeathRecipient. Listen to the death of the INativeSpatializerCallback. */
     virtual void binderDied(const wp<IBinder>& who);
@@ -277,6 +278,9 @@
     /** Callback interface to the client (AudioService) controlling this`Spatializer */
     sp<media::INativeSpatializerCallback> mSpatializerCallback GUARDED_BY(mLock);
 
+    /** Callback interface for head tracking */
+    sp<media::ISpatializerHeadTrackingCallback> mHeadTrackingCallback GUARDED_BY(mLock);
+
     /** Requested spatialization level */
     media::SpatializationLevel mLevel GUARDED_BY(mLock) = media::SpatializationLevel::NONE;