Merge "wifi: Add access network type support"
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index 85d1f57..9cbf343 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -20,7 +20,7 @@
 interface IFingerprint {
   android.hardware.biometrics.fingerprint.SensorProps[] getSensorProps();
   android.hardware.biometrics.fingerprint.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.fingerprint.ISessionCallback cb);
-  void setResetLockoutCallback(in android.hardware.biometrics.fingerprint.IResetLockoutCallback cb);
+  void setLockoutCallback(in android.hardware.biometrics.fingerprint.ILockoutCallback cb);
   void generateChallenge(in int sensorId, in int userId, in int timeoutSec, in android.hardware.biometrics.fingerprint.IGenerateChallengeCallback cb);
-  void revokeChallenge(in int sensorId, in int userId, in android.hardware.biometrics.fingerprint.IRevokeChallengeCallback cb);
+  void revokeChallenge(in int sensorId, in int userId, in long challenge, in android.hardware.biometrics.fingerprint.IRevokeChallengeCallback cb);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
index eaf27d2..063be60 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
@@ -18,5 +18,5 @@
 package android.hardware.biometrics.fingerprint;
 @VintfStability
 interface IGenerateChallengeCallback {
-  oneway void onChallengeGenerated(in int sensorId, in int userId, in long keystoreOperationId, in long challenge);
+  oneway void onChallengeGenerated(in int sensorId, in int userId, in long challenge);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
similarity index 82%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
copy to biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
index ac0decd..88aabbf 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
@@ -17,6 +17,8 @@
 
 package android.hardware.biometrics.fingerprint;
 @VintfStability
-interface IResetLockoutCallback {
-  oneway void onLockoutReset(in int sensorId, in int userId, in long durationMilli);
+interface ILockoutCallback {
+  oneway void onLockoutTimed(in int sensorId, in int userId, in long durationMillis);
+  oneway void onLockoutPermanent(in int sensorId, in int userId);
+  oneway void onLockoutCleared(in int sensorId, in int userId);
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index 4709778..57319b2 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -17,7 +17,7 @@
 package android.hardware.biometrics.fingerprint;
 
 import android.hardware.biometrics.fingerprint.IGenerateChallengeCallback;
-import android.hardware.biometrics.fingerprint.IResetLockoutCallback;
+import android.hardware.biometrics.fingerprint.ILockoutCallback;
 import android.hardware.biometrics.fingerprint.IRevokeChallengeCallback;
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.biometrics.fingerprint.ISessionCallback;
@@ -25,13 +25,144 @@
 
 @VintfStability
 interface IFingerprint {
+    /**
+     * getSensorProps:
+     *
+     * @return A list of properties for all sensors that an instance of the
+     * HAL supports.
+     */
     SensorProps[] getSensorProps();
 
+    /**
+     * createSession:
+     *
+     * Creates a session which can then be used by the framework to perform
+     * operations such as enroll, authenticate, etc for the given sensorId
+     * and userId.
+     *
+     * A physical sensor identified by sensorId typically supports only a
+     * single in-flight session at a time. As such, if a session is currently
+     * in a state other than SessionState::IDLING, the HAL MUST finish or
+     * cancel the current operation and return to SessionState::IDLING before
+     * the new session is created. For example:
+     *   1) If a session for sensorId=0, userId=0
+     *      is currently in a cancellable state (see ICancellationSignal) such
+     *      as SessionState::AUTHENTICATING and the framework requests a new
+     *      session for sensorId=0, userId=10, the HAL must end the current
+     *      session with Error::CANCELED, invoke
+     *      ISessionCallback#onStateChanged with SessionState::IDLING, and
+     *      then return a new session for sensorId=0, userId=10.
+     *   2) If a session for sensorId=0, userId=0 is currently in a
+     *      non-cancellable state such as SessionState::REMOVING_ENROLLMENTS,
+     *      and the framework requests a new session for sensorId=0, userId=10,
+     *      the HAL must finish the current operation before invoking
+     *      ISessionCallback#onStateChanged with SessionState::IDLING, and
+     *      return a new session for sensorId=0, userId=10.
+     *
+     * Implementations must store user-specific state or metadata in
+     * /data/vendor_de/<user>/fpdata as specified by the SeLinux policy. This
+     * directory is created/removed by vold (see vold_prepare_subdirs.cpp).
+     * Implementations may store additional user-specific data, such as
+     * embeddings or templates in StrongBox.
+     *
+     * @param sensorId The sensor with which this session is being created.
+     * @param userId The userId with which this session is being created.
+     * @param cb Used to notify the framework.
+     * @return A new session
+     */
     ISession createSession(in int sensorId, in int userId, in ISessionCallback cb);
 
-    void setResetLockoutCallback(in IResetLockoutCallback cb);
+    /**
+     * setLockoutCallback:
+     *
+     * Sets a callback to notify the framework lockout changes. Note
+     * that lockout is user AND sensor specific. In other words, there is a
+     * separate lockout state for each (user, sensor) pair. For example, the
+     * following is a valid state on a multi-sensor device:
+     * ------------------------------------------------------------------
+     * | SensorId | UserId | FailedAttempts | LockedOut | LockedUntil   |
+     * |----------|--------|----------------|-----------|---------------|
+     * | 0        | 0      | 1              | false     | x             |
+     * | 1        | 0      | 5              | true      | <future_time> |
+     * | 0        | 10     | 0              | false     | x             |
+     * | 1        | 10     | 0              | false     | x             |
+     * ------------------------------------------------------------------
+     *
+     * Lockout may be cleared in the following ways:
+     *   1) ISession#resetLockout
+     *   2) After a period of time, according to a rate-limiter.
+     *
+     * In addition, lockout states MUST persist after device reboots, HAL
+     * crashes, etc.
+     *
+     * See the Android CDD section 7.3.10 for the full set of lockout and
+     * rate-limiting requirements.
+     *
+     * @param cb Used to notify the framework of lockout changes.
+     */
+    void setLockoutCallback(in ILockoutCallback cb);
 
+    /**
+     * generateChallenge:
+     *
+     * Begins a secure transaction request. Note that the challenge by itself
+     * is not useful. It only becomes useful when wrapped in a verifiable
+     * message such as a HardwareAuthToken.
+     *
+     * Canonical example:
+     *   1) User requests an operation, such as fingerprint enrollment.
+     *   2) Fingerprint enrollment cannot happen until the user confirms
+     *      their lockscreen credential (PIN/Pattern/Password).
+     *   3) However, the biometric subsystem does not want just "any"
+     *      proof of credential confirmation. It needs proof that the
+     *      user explicitly authenticated credential in order to allow
+     *      addition of biometric enrollments.
+     * To secure this path, the following path is taken:
+     *   1) Upon user requesting fingerprint enroll, the framework requests
+     *      IFingerprint#generateChallenge
+     *   2) Framework sends the challenge to the credential subsystem, and upon
+     *      credential confirmation, a HAT is created, containing the challenge
+     *      in the "challenge" field.
+     *   3) Framework sends the HAT to the HAL, e.g. ISession#enroll.
+     *   4) Implementation verifies the authenticity and integrity of the HAT.
+     *   5) Implementation now has confidence that the user entered their
+     *      credential to allow biometric enrollment.
+     *
+     * Note that the interface allows multiple in-flight challenges. For
+     * example, invoking generateChallenge(0, 0, timeoutSec, cb) twice
+     * does not invalidate the first challenge. The challenge is invalidated
+     * only when:
+     *   1) The provided timeout expires, or
+     *   2) IFingerprint#revokeChallenge is invoked
+     *
+     * For example, the following is a possible table of valid challenges:
+     * ----------------------------------------------
+     * | SensorId | UserId | ValidUntil | Challenge |
+     * |----------|--------|------------|-----------|
+     * | 0        | 0      | <Time1>    | <Random1> |
+     * | 0        | 0      | <Time2>    | <Random2> |
+     * | 1        | 0      | <Time3>    | <Random3> |
+     * | 0        | 10     | <Time4>    | <Random4> |
+     * ----------------------------------------------
+     *
+     * @param sensorId Sensor to associate the challenge with
+     * @param userId User to associate the challenge with
+     * @param timeoutSec Duration for which the challenge is valid for
+     * @param cb Callback to notify the framework
+     */
     void generateChallenge(in int sensorId, in int userId, in int timeoutSec, in IGenerateChallengeCallback cb);
 
-    void revokeChallenge(in int sensorId, in int userId, in IRevokeChallengeCallback cb);
+    /**
+     * revokeChallenge:
+     *
+     * Revokes a challenge that was previously generated. Note that if an
+     * invalid combination of parameters is requested, the implementation
+     * must still notify the framework using the provided callback.
+     *
+     * @param sensorId Sensor that the revocation should apply to.
+     * @param userId User that the revocation should apply to.
+     * @param challenge Challenge that should be revoked.
+     * @param cb Used to notify the framework.
+     */
+    void revokeChallenge(in int sensorId, in int userId, in long challenge, in IRevokeChallengeCallback cb);
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
index 93a2d7b..a51b188 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
@@ -18,6 +18,9 @@
 
 @VintfStability
 oneway interface IGenerateChallengeCallback {
-    void onChallengeGenerated(in int sensorId, in int userId, in long keystoreOperationId, in long challenge);
+    /**
+     * Notifies the framework when a challenge is successfully generated.
+     */
+    void onChallengeGenerated(in int sensorId, in int userId, in long challenge);
 }
 
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
new file mode 100644
index 0000000..4b31a38
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
@@ -0,0 +1,60 @@
+/*
+ * 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.hardware.biometrics.fingerprint;
+
+@VintfStability
+oneway interface ILockoutCallback {
+    /**
+     * Notifies the framework that the user has just entered the Error::LOCKOUT state. This must be
+     * sent in the following scenarios:
+     * 1) The user just attempted authentication and was rejected, resulting in a timed lockout.
+     * 2) The framework just created a session for a sensorId/userId pair that has not been
+     *    created since the HAL started (e.g. there is no active or idle session for this
+     *    sensorId/userId pair.
+     *
+     * @param sensorId Sensor for which the user is locked out.
+     * @param userId User for which the sensor is locked out.
+     * @param durationMillis Remaining duration of the lockout.
+     */
+    void onLockoutTimed(in int sensorId, in int userId, in long durationMillis);
+
+    /**
+     * Notifies the framework that the user has just entered the Error::LOCKOUT_PERMANENT state.
+     * This must be sent in the following scenarios:
+     * 1) The user just attempted authentication and was rejected, resulting in a permanent lockout.
+     * 2) The framework just created a session for a sensorId/userId pair that has not been
+     *    created since the HAL started (e.g. there is no active or idle session for this
+     *    sensorId/userId pair.
+     *
+     * @param sensorId Sensor for which the user is locked out.
+     * @param userId User for which the sensor is locked out.
+     */
+    void onLockoutPermanent(in int sensorId, in int userId);
+
+    /**
+     * Notifies the framework that lockout has been cleared for this sensorId/userId pair. This
+     * can happen in the following scenarios:
+     * 1) A timed lockout has ended (e.g. original durationMillis specified in #onLockoutTimed
+     *    has expired.
+     * 2) See ISession#resetLockout.
+     *
+     * @param sensorId Sensor for which the user's lockout is cleared.
+     * @param userId User for the sensor's lockout is cleared.
+     */
+    void onLockoutCleared(in int sensorId, in int userId);
+}
+
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IRevokeChallengeCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IRevokeChallengeCallback.aidl
index cca3453..eadba52 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IRevokeChallengeCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IRevokeChallengeCallback.aidl
@@ -18,6 +18,9 @@
 
 @VintfStability
 oneway interface IRevokeChallengeCallback {
+    /**
+     * Notifies the framework when a challenge has been revoked.
+     */
     void onChallengeRevoked(in int sensorId, in int userId, in long challenge);
 }
 
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
index dd340e8..e2d23a6 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -82,12 +82,14 @@
      * The following only applies to sensors that are configured as
      * SensorStrength::STRONG.
      *
-     * When invoked by the framework, the HAL implementation must perform the
+     * When invoked by the framework, the implementation must perform the
      * following sequence of events:
      *   1) Verify the authenticity and integrity of the provided HAT
-     *   2) Update the authenticatorId with a new entropy-encoded random number
-     *   3) Persist the new authenticatorId to non-ephemeral storage
-     *   4) Notify the framework that the above is completed, via
+     *   2) Verify that the timestamp provided within the HAT is relatively
+     *      recent (e.g. on the order of minutes, not hours).
+     *   3) Update the authenticatorId with a new entropy-encoded random number
+     *   4) Persist the new authenticatorId to non-ephemeral storage
+     *   5) Notify the framework that the above is completed, via
      *      ISessionCallback#onAuthenticatorInvalidated
      *
      * A practical use case of invalidation would be when the user adds a new
@@ -105,6 +107,26 @@
      */
     void invalidateAuthenticatorId(in int cookie, in HardwareAuthToken hat);
 
+    /**
+     * resetLockout:
+     *
+     * Requests the implementation to clear the lockout counter. Upon receiving
+     * this request, the implementation must perform the following:
+     *   1) Verify the authenticity and integrity of the provided HAT
+     *   2) Verify that the timestamp provided within the HAT is relatively
+     *      recent (e.g. on the order of minutes, not hours).
+     *
+     * Upon successful verification, the HAL must notify the framework via
+     * ILockoutCallback#onLockoutChanged(sensorId, userId, 0).
+     *
+     * If verification was uncessful, the HAL must notify the framework via
+     * ILockoutCallback#onLockoutChanged(sensorId, userId, remaining_time).
+     *
+     * @param cookie An identifier used to track subsystem operations related
+     *               to this call path. The framework will guarantee that it is
+     *               unique per ISession.
+     * @param hat HardwareAuthToken See above documentation.
+     */
     void resetLockout(in int cookie, in HardwareAuthToken hat);
 
 
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index a1d9d0a..b3bd4e7 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -61,8 +61,8 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Fingerprint::setResetLockoutCallback(
-        const std::shared_ptr<IResetLockoutCallback>& /*cb*/) {
+ndk::ScopedAStatus Fingerprint::setLockoutCallback(
+        const std::shared_ptr<ILockoutCallback>& /*cb*/) {
     return ndk::ScopedAStatus::ok();
 }
 
@@ -73,7 +73,7 @@
 }
 
 ndk::ScopedAStatus Fingerprint::revokeChallenge(
-        int32_t /*sensorId*/, int32_t /*userId*/,
+        int32_t /*sensorId*/, int32_t /*userId*/, int64_t /*challenge*/,
         const std::shared_ptr<IRevokeChallengeCallback>& /*cb*/) {
     return ndk::ScopedAStatus::ok();
 }
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.h b/biometrics/fingerprint/aidl/default/Fingerprint.h
index b5b09c0..463d07d 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.h
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.h
@@ -28,15 +28,15 @@
                                      const std::shared_ptr<ISessionCallback>& cb,
                                      std::shared_ptr<ISession>* _aidl_return) override;
 
-    ndk::ScopedAStatus setResetLockoutCallback(
-            const std::shared_ptr<IResetLockoutCallback>& cb) override;
+    ndk::ScopedAStatus setLockoutCallback(
+            const std::shared_ptr<ILockoutCallback>& cb) override;
 
     ndk::ScopedAStatus generateChallenge(
             int32_t sensorId, int32_t userId, int32_t timeoutSec,
             const std::shared_ptr<IGenerateChallengeCallback>& cb) override;
 
     ndk::ScopedAStatus revokeChallenge(
-            int32_t sensorId, int32_t userId,
+            int32_t sensorId, int32_t userId, int64_t challenge,
             const std::shared_ptr<IRevokeChallengeCallback>& cb) override;
 };
 
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/SynchronizedReadWrite.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
copy to common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/SynchronizedReadWrite.aidl
index ac0decd..aec3d6d 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/SynchronizedReadWrite.aidl
@@ -15,8 +15,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.common;
 @VintfStability
-interface IResetLockoutCallback {
-  oneway void onLockoutReset(in int sensorId, in int userId, in long durationMilli);
+enum SynchronizedReadWrite {
+  EMPTY = 0,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
similarity index 85%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
rename to common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
index ac0decd..e390d20 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/UnsynchronizedWrite.aidl
@@ -15,8 +15,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.common;
 @VintfStability
-interface IResetLockoutCallback {
-  oneway void onLockoutReset(in int sensorId, in int userId, in long durationMilli);
+enum UnsynchronizedWrite {
+  EMPTY = 0,
 }
diff --git a/common/aidl/android/hardware/common/MQDescriptor.aidl b/common/aidl/android/hardware/common/MQDescriptor.aidl
index 8997688..7e89b15 100644
--- a/common/aidl/android/hardware/common/MQDescriptor.aidl
+++ b/common/aidl/android/hardware/common/MQDescriptor.aidl
@@ -22,9 +22,12 @@
  * For use with libfmq. This is created from an instance of AidlMessageQueue,
  * and is used to pass information required to create another instance of that
  * queue for fast communication.
+ * T - is used to specify the type of the payload
+ * Flavor - is used to specify the type of the queue using
+ * android.hardware.common.SynchronizedReadWrite or UnsynchronizedWrite
  */
 @VintfStability
-parcelable MQDescriptor {
+parcelable MQDescriptor<T, Flavor> {
     /*
      * Describes each of the grantors for the message queue. They are used to
      * get the readptr, writeptr, dataptr, and the optional EventFlag word
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl b/common/aidl/android/hardware/common/SynchronizedReadWrite.aidl
similarity index 62%
rename from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
rename to common/aidl/android/hardware/common/SynchronizedReadWrite.aidl
index d97a701..ef93bf2 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
+++ b/common/aidl/android/hardware/common/SynchronizedReadWrite.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright 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.
@@ -14,10 +14,14 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.common;
 
+/*
+ * For use with android.hardware.common.MQDescriptor to specify which type of
+ * queue to use. SynchronizedReadWrite is single reader, single writer, with no
+ * overflow. All messages written need to be read.
+ */
 @VintfStability
-oneway interface IResetLockoutCallback {
-    void onLockoutReset(in int sensorId, in int userId, in long durationMilli);
+enum SynchronizedReadWrite {
+    EMPTY,
 }
-
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl b/common/aidl/android/hardware/common/UnsynchronizedWrite.aidl
similarity index 61%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
copy to common/aidl/android/hardware/common/UnsynchronizedWrite.aidl
index d97a701..aa27c8d 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
+++ b/common/aidl/android/hardware/common/UnsynchronizedWrite.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright 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.
@@ -14,10 +14,14 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.common;
 
+/*
+ * For use with android.hardware.common.MQDescriptor to specify which type of
+ * queue to use. UnsynchronizedWrite is single writer, multiple reader, with
+ * overflow. If messages are not read fast enough, they can be overwritten.
+ */
 @VintfStability
-oneway interface IResetLockoutCallback {
-    void onLockoutReset(in int sensorId, in int userId, in long durationMilli);
+enum UnsynchronizedWrite {
+    EMPTY,
 }
-
diff --git a/tests/msgq/1.0/ITestMsgQ.hal b/tests/msgq/1.0/ITestMsgQ.hal
index 112270a..bd10237 100644
--- a/tests/msgq/1.0/ITestMsgQ.hal
+++ b/tests/msgq/1.0/ITestMsgQ.hal
@@ -31,7 +31,7 @@
      *
      * @return ret True if the setup is successful.
      */
-    configureFmqSyncReadWrite(fmq_sync<uint16_t> mqDesc) generates(bool ret);
+    configureFmqSyncReadWrite(fmq_sync<int32_t> mqDesc) generates(bool ret);
 
     /**
      * This method requests the service to return an MQDescriptor to
@@ -46,7 +46,7 @@
      * @return mqDesc This structure describes the unsynchronized FMQ that was
      * set up by the service. Client can use it to set up the FMQ at its end.
      */
-    getFmqUnsyncWrite(bool configureFmq) generates(bool ret, fmq_unsync<uint16_t> mqDesc);
+    getFmqUnsyncWrite(bool configureFmq) generates(bool ret, fmq_unsync<int32_t> mqDesc);
 
     /**
      * This method request the service to write into the synchronized read/write
diff --git a/tests/msgq/1.0/default/TestMsgQ.cpp b/tests/msgq/1.0/default/TestMsgQ.cpp
index ba665c9..4473737 100644
--- a/tests/msgq/1.0/default/TestMsgQ.cpp
+++ b/tests/msgq/1.0/default/TestMsgQ.cpp
@@ -25,7 +25,7 @@
 
 // Methods from ::android::hardware::tests::msgq::V1_0::ITestMsgQ follow.
 Return<bool> TestMsgQ::configureFmqSyncReadWrite(
-    const android::hardware::MQDescriptorSync<uint16_t>& mqDesc) {
+        const android::hardware::MQDescriptorSync<int32_t>& mqDesc) {
     mFmqSynchronized.reset(new (std::nothrow) MessageQueueSync(mqDesc));
     if ((mFmqSynchronized == nullptr) || (mFmqSynchronized->isValid() == false)) {
         return false;
@@ -56,7 +56,7 @@
 }
 
 Return<bool> TestMsgQ::requestWriteFmqSync(int32_t count) {
-    std::vector<uint16_t> data(count);
+    std::vector<int32_t> data(count);
     for (int i = 0; i < count; i++) {
         data[i] = i;
     }
@@ -65,14 +65,14 @@
 }
 
 Return<bool> TestMsgQ::requestReadFmqSync(int32_t count) {
-    std::vector<uint16_t> data(count);
+    std::vector<int32_t> data(count);
     bool result = mFmqSynchronized->read(&data[0], count)
             && verifyData(&data[0], count);
     return result;
 }
 
 Return<bool> TestMsgQ::requestWriteFmqUnsync(int32_t count) {
-    std::vector<uint16_t> data(count);
+    std::vector<int32_t> data(count);
     for (int i = 0; i < count; i++) {
         data[i] = i;
     }
@@ -81,14 +81,14 @@
 }
 
 Return<bool> TestMsgQ::requestReadFmqUnsync(int32_t count) {
-    std::vector<uint16_t> data(count);
+    std::vector<int32_t> data(count);
     bool result =
             mFmqUnsynchronized->read(&data[0], count) && verifyData(&data[0], count);
     return result;
 }
 
 Return<void> TestMsgQ::requestBlockingRead(int32_t count) {
-    std::vector<uint16_t> data(count);
+    std::vector<int32_t> data(count);
     bool result = mFmqSynchronized->readBlocking(
             &data[0],
             count,
@@ -103,7 +103,7 @@
 }
 
 Return<void> TestMsgQ::requestBlockingReadDefaultEventFlagBits(int32_t count) {
-    std::vector<uint16_t> data(count);
+    std::vector<int32_t> data(count);
     bool result = mFmqSynchronized->readBlocking(
             &data[0],
             count);
@@ -116,7 +116,7 @@
 }
 
 Return<void> TestMsgQ::requestBlockingReadRepeat(int32_t count, int32_t numIter) {
-    std::vector<uint16_t> data(count);
+    std::vector<int32_t> data(count);
     for (int i = 0; i < numIter; i++) {
         bool result = mFmqSynchronized->readBlocking(
                 &data[0],
diff --git a/tests/msgq/1.0/default/TestMsgQ.h b/tests/msgq/1.0/default/TestMsgQ.h
index f9fcddd..8a204b7 100644
--- a/tests/msgq/1.0/default/TestMsgQ.h
+++ b/tests/msgq/1.0/default/TestMsgQ.h
@@ -49,13 +49,13 @@
 using android::hardware::MessageQueue;
 
 struct TestMsgQ : public ITestMsgQ {
-    typedef MessageQueue<uint16_t, kSynchronizedReadWrite> MessageQueueSync;
-    typedef MessageQueue<uint16_t, kUnsynchronizedWrite> MessageQueueUnsync;
+    typedef MessageQueue<int32_t, kSynchronizedReadWrite> MessageQueueSync;
+    typedef MessageQueue<int32_t, kUnsynchronizedWrite> MessageQueueUnsync;
 
     TestMsgQ() : mFmqSynchronized(nullptr), mFmqUnsynchronized(nullptr) {}
 
     // Methods from ::android::hardware::tests::msgq::V1_0::ITestMsgQ follow.
-    Return<bool> configureFmqSyncReadWrite(const MQDescriptorSync<uint16_t>& mqDesc) override;
+    Return<bool> configureFmqSyncReadWrite(const MQDescriptorSync<int32_t>& mqDesc) override;
     Return<void> getFmqUnsyncWrite(bool configureFmq, getFmqUnsyncWrite_cb _hidl_cb) override;
     Return<bool> requestWriteFmqSync(int32_t count) override;
     Return<bool> requestReadFmqSync(int32_t count) override;
@@ -73,7 +73,7 @@
     /*
      * Utility function to verify data read from the fast message queue.
      */
-    bool verifyData(uint16_t* data, int count) {
+    bool verifyData(int32_t* data, int count) {
         for (int i = 0; i < count; i++) {
             if (data[i] != i) return false;
         }
diff --git a/tv/tuner/1.1/IFilter.hal b/tv/tuner/1.1/IFilter.hal
index b362e32..2ba9bb7 100644
--- a/tv/tuner/1.1/IFilter.hal
+++ b/tv/tuner/1.1/IFilter.hal
@@ -51,4 +51,23 @@
      *         UNKNOWN_ERROR if failed for other reasons.
      */
     configureIpCid(uint32_t ipCid) generates (Result result);
+
+    /**
+     * Get the shared AV memory handle. Use IFilter.releaseAvHandle to release the handle.
+     *
+     * When media filters are opened, call this API to initialize the share memory handle if it's
+     * needed.
+     *
+     * If DemuxFilterMediaEvent.avMemory contains file descriptor, share memory should be ignored.
+     *
+     * @return avMemory A handle associated to the shared memory for audio or video.
+     *         avMemory.data[0] is normally an fd for ION memory. When the avMemory->numFd is 0, the
+     *         share memory is not initialized and does not contain valid fd.
+     *         avMemory.data[avMemory.numFds] is an index used as a parameter of
+     *         C2DataIdInfo to build C2 buffer in Codec. No C2 buffer would be created if the index
+     *         does not exist.
+     * @return avMemSize the size of the shared av memory. It should be ignored when the share
+     *         memory is not initialized.
+     */
+    getAvSharedHandle() generates (Result result, handle avMemory, uint64_t avMemSize);
 };
diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp
index 3db8b9e..c69beca 100644
--- a/tv/tuner/1.1/default/Filter.cpp
+++ b/tv/tuner/1.1/default/Filter.cpp
@@ -163,8 +163,17 @@
     return Result::SUCCESS;
 }
 
-Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t avDataId) {
+Return<Result> Filter::releaseAvHandle(const hidl_handle& avMemory, uint64_t avDataId) {
     ALOGV("%s", __FUNCTION__);
+
+    if ((avMemory.getNativeHandle()->numFds > 0) &&
+        (mSharedAvMemHandle.getNativeHandle()->numFds > 0) &&
+        (sameFile(avMemory.getNativeHandle()->data[0],
+                  mSharedAvMemHandle.getNativeHandle()->data[0]))) {
+        freeSharedAvHandle();
+        return Result::SUCCESS;
+    }
+
     if (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) {
         return Result::INVALID_ARGUMENT;
     }
@@ -190,6 +199,35 @@
     return Result::SUCCESS;
 }
 
+Return<void> Filter::getAvSharedHandle(getAvSharedHandle_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (!mIsMediaFilter) {
+        _hidl_cb(Result::INVALID_STATE, NULL, BUFFER_SIZE_16M);
+        return Void();
+    }
+
+    if (mSharedAvMemHandle.getNativeHandle() != nullptr) {
+        _hidl_cb(Result::SUCCESS, mSharedAvMemHandle, BUFFER_SIZE_16M);
+        return Void();
+    }
+
+    int av_fd = createAvIonFd(BUFFER_SIZE_16M);
+    if (av_fd == -1) {
+        _hidl_cb(Result::UNKNOWN_ERROR, NULL, 0);
+    }
+
+    native_handle_t* nativeHandle = createNativeHandle(av_fd);
+    if (nativeHandle == NULL) {
+        _hidl_cb(Result::UNKNOWN_ERROR, NULL, 0);
+    }
+    mSharedAvMemHandle.setTo(nativeHandle, /*shouldOwn=*/true);
+    ::close(av_fd);
+
+    _hidl_cb(Result::SUCCESS, mSharedAvMemHandle, BUFFER_SIZE_16M);
+    return Void();
+}
+
 bool Filter::createFilterMQ() {
     ALOGV("%s", __FUNCTION__);
 
@@ -313,10 +351,19 @@
     }
     for (int i = 0; i < mFilterEvent.events.size(); i++) {
         ::close(mFilterEvent.events[i].media().avMemory.getNativeHandle()->data[0]);
-        native_handle_close(mFilterEvent.events[i].media().avMemory.getNativeHandle());
+        native_handle_delete(const_cast<native_handle_t*>(
+                mFilterEvent.events[i].media().avMemory.getNativeHandle()));
     }
 }
 
+void Filter::freeSharedAvHandle() {
+    if (!mIsMediaFilter) {
+        return;
+    }
+    ::close(mSharedAvMemHandle.getNativeHandle()->data[0]);
+    native_handle_delete(const_cast<native_handle_t*>(mSharedAvMemHandle.getNativeHandle()));
+}
+
 void Filter::maySendFilterStatusCallback() {
     if (!mIsUsingFMQ) {
         return;
@@ -509,8 +556,8 @@
         return Result::SUCCESS;
     }
 
+    Result result;
     if (mPts) {
-        Result result;
         result = createMediaFilterEventWithIon(mFilterOutput);
         if (result == Result::SUCCESS) {
             mFilterOutput.clear();
@@ -551,7 +598,10 @@
             continue;
         }
 
-        createMediaFilterEventWithIon(mPesOutput);
+        result = createMediaFilterEventWithIon(mPesOutput);
+        if (result != Result::SUCCESS) {
+            return result;
+        }
     }
 
     mFilterOutput.clear();
@@ -560,51 +610,14 @@
 }
 
 Result Filter::createMediaFilterEventWithIon(vector<uint8_t> output) {
-    int av_fd = createAvIonFd(output.size());
-    if (av_fd == -1) {
-        return Result::UNKNOWN_ERROR;
+    if (mUsingSharedAvMem) {
+        if (mSharedAvMemHandle.getNativeHandle() == nullptr) {
+            return Result::UNKNOWN_ERROR;
+        }
+        return createShareMemMediaEvents(output);
     }
-    // copy the filtered data to the buffer
-    uint8_t* avBuffer = getIonBuffer(av_fd, output.size());
-    if (avBuffer == NULL) {
-        return Result::UNKNOWN_ERROR;
-    }
-    memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t));
 
-    native_handle_t* nativeHandle = createNativeHandle(av_fd);
-    if (nativeHandle == NULL) {
-        return Result::UNKNOWN_ERROR;
-    }
-    hidl_handle handle;
-    handle.setTo(nativeHandle, /*shouldOwn=*/true);
-
-    // Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
-    uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
-    mDataId2Avfd[dataId] = dup(av_fd);
-
-    // Create mediaEvent and send callback
-    DemuxFilterMediaEvent mediaEvent;
-    mediaEvent = {
-            .avMemory = std::move(handle),
-            .dataLength = static_cast<uint32_t>(output.size()),
-            .avDataId = dataId,
-    };
-    if (mPts) {
-        mediaEvent.pts = mPts;
-        mPts = 0;
-    }
-    int size = mFilterEvent.events.size();
-    mFilterEvent.events.resize(size + 1);
-    mFilterEvent.events[size].media(mediaEvent);
-
-    // Clear and log
-    output.clear();
-    mAvBufferCopyCount = 0;
-    ::close(av_fd);
-    if (DEBUG_FILTER) {
-        ALOGD("[Filter] av data length %d", mediaEvent.dataLength);
-    }
-    return Result::SUCCESS;
+    return createIndependentMediaEvents(output);
 }
 
 Result Filter::startRecordFilterHandler() {
@@ -713,15 +726,119 @@
 }
 
 native_handle_t* Filter::createNativeHandle(int fd) {
-    // Create a native handle to pass the av fd via the callback event.
-    native_handle_t* nativeHandle = native_handle_create(/*numFd*/ 1, 0);
+    native_handle_t* nativeHandle;
+    if (fd < 0) {
+        nativeHandle = native_handle_create(/*numFd*/ 0, 0);
+    } else {
+        // Create a native handle to pass the av fd via the callback event.
+        nativeHandle = native_handle_create(/*numFd*/ 1, 0);
+    }
     if (nativeHandle == NULL) {
         ALOGE("[Filter] Failed to create native_handle %d", errno);
         return NULL;
     }
-    nativeHandle->data[0] = dup(fd);
+    if (nativeHandle->numFds > 0) {
+        nativeHandle->data[0] = dup(fd);
+    }
     return nativeHandle;
 }
+
+Result Filter::createIndependentMediaEvents(vector<uint8_t> output) {
+    int av_fd = createAvIonFd(output.size());
+    if (av_fd == -1) {
+        return Result::UNKNOWN_ERROR;
+    }
+    // copy the filtered data to the buffer
+    uint8_t* avBuffer = getIonBuffer(av_fd, output.size());
+    if (avBuffer == NULL) {
+        return Result::UNKNOWN_ERROR;
+    }
+    memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t));
+
+    native_handle_t* nativeHandle = createNativeHandle(av_fd);
+    if (nativeHandle == NULL) {
+        return Result::UNKNOWN_ERROR;
+    }
+    hidl_handle handle;
+    handle.setTo(nativeHandle, /*shouldOwn=*/true);
+
+    // Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
+    uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
+    mDataId2Avfd[dataId] = dup(av_fd);
+
+    // Create mediaEvent and send callback
+    DemuxFilterMediaEvent mediaEvent;
+    mediaEvent = {
+            .avMemory = std::move(handle),
+            .dataLength = static_cast<uint32_t>(output.size()),
+            .avDataId = dataId,
+    };
+    if (mPts) {
+        mediaEvent.pts = mPts;
+        mPts = 0;
+    }
+    int size = mFilterEvent.events.size();
+    mFilterEvent.events.resize(size + 1);
+    mFilterEvent.events[size].media(mediaEvent);
+
+    // Clear and log
+    output.clear();
+    mAvBufferCopyCount = 0;
+    ::close(av_fd);
+    if (DEBUG_FILTER) {
+        ALOGD("[Filter] av data length %d", mediaEvent.dataLength);
+    }
+    return Result::SUCCESS;
+}
+
+Result Filter::createShareMemMediaEvents(vector<uint8_t> output) {
+    // copy the filtered data to the shared buffer
+    uint8_t* sharedAvBuffer = getIonBuffer(mSharedAvMemHandle.getNativeHandle()->data[0],
+                                           output.size() + mSharedAvMemOffset);
+    if (sharedAvBuffer == NULL) {
+        return Result::UNKNOWN_ERROR;
+    }
+    memcpy(sharedAvBuffer + mSharedAvMemOffset, output.data(), output.size() * sizeof(uint8_t));
+
+    // Create a memory handle with numFds == 0
+    native_handle_t* nativeHandle = createNativeHandle(-1);
+    if (nativeHandle == NULL) {
+        return Result::UNKNOWN_ERROR;
+    }
+    hidl_handle handle;
+    handle.setTo(nativeHandle, /*shouldOwn=*/true);
+
+    // Create mediaEvent and send callback
+    DemuxFilterMediaEvent mediaEvent;
+    mediaEvent = {
+            .offset = static_cast<uint32_t>(mSharedAvMemOffset),
+            .dataLength = static_cast<uint32_t>(output.size()),
+            .avMemory = handle,
+    };
+    mSharedAvMemOffset += output.size();
+    if (mPts) {
+        mediaEvent.pts = mPts;
+        mPts = 0;
+    }
+    int size = mFilterEvent.events.size();
+    mFilterEvent.events.resize(size + 1);
+    mFilterEvent.events[size].media(mediaEvent);
+
+    // Clear and log
+    output.clear();
+    if (DEBUG_FILTER) {
+        ALOGD("[Filter] shared av data length %d", mediaEvent.dataLength);
+    }
+    return Result::SUCCESS;
+}
+
+bool Filter::sameFile(int fd1, int fd2) {
+    struct stat stat1, stat2;
+    if (fstat(fd1, &stat1) < 0 || fstat(fd2, &stat2) < 0) {
+        return false;
+    }
+    return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
+}
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace tuner
diff --git a/tv/tuner/1.1/default/Filter.h b/tv/tuner/1.1/default/Filter.h
index 23bc25c..f677666 100644
--- a/tv/tuner/1.1/default/Filter.h
+++ b/tv/tuner/1.1/default/Filter.h
@@ -23,6 +23,7 @@
 #include <inttypes.h>
 #include <ion/ion.h>
 #include <math.h>
+#include <sys/stat.h>
 #include <set>
 #include "Demux.h"
 #include "Dvr.h"
@@ -43,6 +44,7 @@
 using ::android::hardware::MQDescriptorSync;
 
 using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+const uint32_t BUFFER_SIZE_16M = 0x1000000;
 
 class Demux;
 class Dvr;
@@ -78,6 +80,8 @@
 
     virtual Return<Result> configureIpCid(uint32_t ipCid) override;
 
+    virtual Return<void> getAvSharedHandle(getAvSharedHandle_cb _hidl_cb) override;
+
     /**
      * To create a FilterMQ and its Event Flag.
      *
@@ -93,6 +97,7 @@
     void attachFilterToRecord(const sp<Dvr> dvr);
     void detachFilterFromRecord();
     void freeAvHandle();
+    void freeSharedAvHandle();
     bool isMediaFilter() { return mIsMediaFilter; };
     bool isPcrFilter() { return mIsPcrFilter; };
     bool isRecordFilter() { return mIsRecordFilter; };
@@ -185,6 +190,9 @@
     uint8_t* getIonBuffer(int fd, int size);
     native_handle_t* createNativeHandle(int fd);
     Result createMediaFilterEventWithIon(vector<uint8_t> output);
+    Result createIndependentMediaEvents(vector<uint8_t> output);
+    Result createShareMemMediaEvents(vector<uint8_t> output);
+    bool sameFile(int fd1, int fd2);
 
     /**
      * Lock to protect writes to the FMQs
@@ -212,6 +220,11 @@
     std::map<uint64_t, int> mDataId2Avfd;
     uint64_t mLastUsedDataId = 1;
     int mAvBufferCopyCount = 0;
+
+    // Shared A/V memory handle
+    hidl_handle mSharedAvMemHandle;
+    bool mUsingSharedAvMem = true;
+    uint32_t mSharedAvMemOffset = 0;
 };
 
 }  // namespace implementation
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.cpp b/tv/tuner/1.1/vts/functional/FilterTests.cpp
index 7e5b549..5a8985d 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp
@@ -16,22 +16,70 @@
 
 #include "FilterTests.h"
 
-bool FilterCallback::readFilterEventData() {
-    bool result = false;
-    ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
+void FilterCallback::testFilterDataOutput() {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (mPidFilterOutputCount < 1) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
+            return;
+        }
+    }
+    mPidFilterOutputCount = 0;
+    ALOGW("[vts] pass and stop");
+}
+
+void FilterCallback::readFilterEventData() {
+    ALOGW("[vts] reading filter event");
     // todo separate filter handlers
+    for (int i = 0; i < mFilterEvent.events.size(); i++) {
+        auto event = mFilterEvent.events[i];
+        switch (event.getDiscriminator()) {
+            case DemuxFilterEvent::Event::hidl_discriminator::media:
+                ALOGD("[vts] Media filter event, avMemHandle numFds=%d.",
+                      event.media().avMemory.getNativeHandle()->numFds);
+                dumpAvData(event.media());
+                break;
+            default:
+                break;
+        }
+    }
     for (int i = 0; i < mFilterEventExt.events.size(); i++) {
         auto eventExt = mFilterEventExt.events[i];
         switch (eventExt.getDiscriminator()) {
             case DemuxFilterEventExt::Event::hidl_discriminator::tsRecord:
-                ALOGW("[vts] Extended TS record filter event, pts=%" PRIu64 ".",
+                ALOGD("[vts] Extended TS record filter event, pts=%" PRIu64 ".",
                       eventExt.tsRecord().pts);
                 break;
             default:
                 break;
         }
     }
-    return result;
+}
+
+bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
+    uint32_t length = event.dataLength;
+    uint32_t offset = event.offset;
+    // read data from buffer pointed by a handle
+    hidl_handle handle = event.avMemory;
+    if (handle.getNativeHandle()->numFds == 0) {
+        if (mAvSharedHandle == NULL) {
+            return false;
+        }
+        handle = mAvSharedHandle;
+    }
+
+    int av_fd = handle.getNativeHandle()->data[0];
+    uint8_t* buffer =
+            static_cast<uint8_t*>(mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0));
+    if (buffer == MAP_FAILED) {
+        ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
+        return false;
+    }
+    uint8_t output[length + 1];
+    memcpy(output, buffer + offset, length);
+    // print buffer and check with golden output.
+    ::close(av_fd);
+    return true;
 }
 
 AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
@@ -81,6 +129,33 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
+AssertionResult FilterTests::getSharedAvMemoryHandle(uint64_t filterId) {
+    EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
+    Result status = Result::UNKNOWN_ERROR;
+    sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
+            android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]);
+    if (filter_v1_1 != NULL) {
+        filter_v1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
+            status = r;
+            if (status == Result::SUCCESS) {
+                mFilterCallbacks[mFilterId]->setSharedHandle(avMemory);
+                mFilterCallbacks[mFilterId]->setMemSize(avMemSize);
+                mAvSharedHandle = avMemory;
+            }
+        });
+    }
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::releaseShareAvHandle(uint64_t filterId) {
+    Result status;
+    EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
+    EXPECT_TRUE(mAvSharedHandle) << "No shared av handle to release.";
+    status = mFilters[filterId]->releaseAvHandle(mAvSharedHandle, 0 /*dataId*/);
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
 AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint64_t filterId) {
     Result status;
     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.h b/tv/tuner/1.1/vts/functional/FilterTests.h
index a47f631..bc6db86 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.h
+++ b/tv/tuner/1.1/vts/functional/FilterTests.h
@@ -46,6 +46,7 @@
 using android::hardware::Void;
 using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
 using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
 using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
 using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
 using android::hardware::tv::tuner::V1_0::DemuxFilterType;
@@ -93,7 +94,14 @@
     }
 
     virtual Return<void> onFilterEvent(
-            const android::hardware::tv::tuner::V1_0::DemuxFilterEvent& /*filterEvent*/) override {
+            const android::hardware::tv::tuner::V1_0::DemuxFilterEvent& filterEvent) override {
+        android::Mutex::Autolock autoLock(mMsgLock);
+        // Temprarily we treat the first coming back filter data on the matching pid a success
+        // once all of the MQ are cleared, means we got all the expected output
+        mFilterEvent = filterEvent;
+        readFilterEventData();
+        mPidFilterOutputCount++;
+        mMsgCondition.signal();
         return Void();
     }
 
@@ -104,8 +112,13 @@
     void setFilterId(uint32_t filterId) { mFilterId = filterId; }
     void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
     void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
+    void setSharedHandle(hidl_handle sharedHandle) { mAvSharedHandle = sharedHandle; }
+    void setMemSize(uint64_t size) { mAvSharedMemSize = size; }
 
-    bool readFilterEventData();
+    void testFilterDataOutput();
+
+    void readFilterEventData();
+    bool dumpAvData(DemuxFilterMediaEvent event);
 
   private:
     uint32_t mFilterId;
@@ -114,6 +127,9 @@
     DemuxFilterEvent mFilterEvent;
     DemuxFilterEventExt mFilterEventExt;
 
+    hidl_handle mAvSharedHandle = NULL;
+    uint64_t mAvSharedMemSize = -1;
+
     android::Mutex mMsgLock;
     android::Mutex mFilterOutputLock;
     android::Condition mMsgCondition;
@@ -127,10 +143,12 @@
     void setDemux(sp<IDemux> demux) { mDemux = demux; }
     sp<IFilter> getFilterById(uint64_t filterId) { return mFilters[filterId]; }
 
-    std::map<uint64_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
+    map<uint64_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
 
     AssertionResult openFilterInDemux(DemuxFilterType type, uint32_t bufferSize);
     AssertionResult getNewlyOpenedFilterId_64bit(uint64_t& filterId);
+    AssertionResult getSharedAvMemoryHandle(uint64_t filterId);
+    AssertionResult releaseShareAvHandle(uint64_t filterId);
     AssertionResult configFilter(DemuxFilterSettings setting, uint64_t filterId);
     AssertionResult configIpFilterCid(uint32_t ipCid, uint64_t filterId);
     AssertionResult getFilterMQDescriptor(uint64_t filterId);
@@ -193,12 +211,14 @@
     sp<ITuner> mService;
     sp<IFilter> mFilter;
     sp<IDemux> mDemux;
-    std::map<uint64_t, sp<IFilter>> mFilters;
-    std::map<uint64_t, sp<FilterCallback>> mFilterCallbacks;
+    map<uint64_t, sp<IFilter>> mFilters;
+    map<uint64_t, sp<FilterCallback>> mFilterCallbacks;
 
     sp<FilterCallback> mFilterCallback;
     MQDesc mFilterMQDescriptor;
     vector<uint64_t> mUsedFilterIds;
 
+    hidl_handle mAvSharedHandle = NULL;
+
     uint64_t mFilterId = -1;
 };
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index e06de53..f87fa3c 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -18,6 +18,10 @@
 
 namespace {
 
+AssertionResult TunerBroadcastHidlTest::filterDataOutputTest() {
+    return filterDataOutputTestBase(mFilterTests);
+}
+
 void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
                                                         FrontendConfig frontendConf) {
     uint32_t feId;
@@ -46,6 +50,38 @@
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
+void TunerBroadcastHidlTest::mediaFilterUsingSharedMemoryTest(FilterConfig filterConf,
+                                                              FrontendConfig frontendConf) {
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    uint64_t filterId;
+
+    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFrontendTests.setDemux(demux);
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+    ASSERT_TRUE(mFilterTests.getSharedAvMemoryHandle(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    // tune test
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    ASSERT_TRUE(filterDataOutputTest());
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mFilterTests.releaseShareAvHandle(filterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
 void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
                                                  FrontendConfig frontendConf, DvrConfig dvrConf) {
     uint32_t feId;
@@ -116,6 +152,16 @@
     mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
 }
 
+TEST_P(TunerBroadcastHidlTest, MediaFilterWithSharedMemoryHandle) {
+    description("Test the Media Filter with shared memory handle");
+    mediaFilterUsingSharedMemoryTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, TunerBroadcastHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, TunerFrontendHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
index 47004f6..f77a740 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
@@ -26,6 +26,20 @@
     initDvrConfig();
 }
 
+static AssertionResult success() {
+    return ::testing::AssertionSuccess();
+}
+
+AssertionResult filterDataOutputTestBase(FilterTests tests) {
+    // Data Verify Module
+    std::map<uint64_t, sp<FilterCallback>>::iterator it;
+    std::map<uint64_t, sp<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
+    for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
+        it->second->testFilterDataOutput();
+    }
+    return success();
+}
+
 class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
@@ -103,4 +117,34 @@
 };
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFrontendHidlTest);
+
+class TunerBroadcastHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mService = ITuner::getService(GetParam());
+        ASSERT_NE(mService, nullptr);
+        initConfiguration();
+
+        mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    sp<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+
+    AssertionResult filterDataOutputTest();
+
+    void mediaFilterUsingSharedMemoryTest(FilterConfig filterConf, FrontendConfig frontendConf);
+};
+
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastHidlTest);
 }  // namespace
\ No newline at end of file