Merge "KM VTS test fix - handled "null" value for imei." into udc-dev
diff --git a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp
index f4e3b5a..4e7e963 100644
--- a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp
+++ b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp
@@ -53,17 +53,25 @@
 namespace audiohalcommon = android::hardware::audio::common;
 namespace audiomediacommon = android::media::audio::common;
 
+namespace {
+constexpr int32_t kAidlVersionThree = 3;
+}
+
 class AudioControlAidl : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
         audioControl = android::waitForDeclaredService<IAudioControl>(String16(GetParam().c_str()));
         ASSERT_NE(audioControl, nullptr);
+        aidlVersion = audioControl->getInterfaceVersion();
     }
 
     void TearDown() override { audioControl = nullptr; }
 
+    bool isAidlVersionAtleast(int version) const { return aidlVersion >= version; }
+
     sp<IAudioControl> audioControl;
     int32_t capabilities;
+    int32_t aidlVersion;
 };
 
 TEST_P(AudioControlAidl, OnSetFadeTowardsFront) {
@@ -250,6 +258,11 @@
 
 TEST_P(AudioControlAidl, RegisterModuleChangeCallbackTwiceThrowsException) {
     ALOGI("Register Module change callback test");
+    if (!isAidlVersionAtleast(kAidlVersionThree)) {
+        GTEST_SKIP() << "Device does not support the new APIs for module change callback";
+        return;
+    }
+
     // make sure no stale callbacks.
     audioControl->clearModuleChangeCallback();
 
@@ -269,6 +282,11 @@
 
 TEST_P(AudioControlAidl, RegisterModuleChangeNullCallbackThrowsException) {
     ALOGI("Register Module change callback with nullptr test");
+    if (!isAidlVersionAtleast(kAidlVersionThree)) {
+        GTEST_SKIP() << "Device does not support the new APIs for module change callback";
+        return;
+    }
+
     auto status = audioControl->setModuleChangeCallback(nullptr);
     EXPECT_THAT(status.exceptionCode(),
                 AnyOf(Eq(Status::EX_ILLEGAL_ARGUMENT), Eq(Status::EX_UNSUPPORTED_OPERATION)));
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index 94d4c88..eb74fa2 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -125,7 +125,8 @@
 
     MacedPublicKey macedPublicKey;
     std::vector<uint8_t> attestationKey;
-    result = rpc->generateEcdsaP256KeyPair(/*testMode=*/true, &macedPublicKey, &attestationKey);
+    // Start by RPC version 3, we don't support testMode=true. So just verify testMode=false here.
+    result = rpc->generateEcdsaP256KeyPair(/*testMode=*/false, &macedPublicKey, &attestationKey);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
 
     optional<vector<vector<uint8_t>>> remotelyProvisionedCertChain =
@@ -176,7 +177,8 @@
 
     MacedPublicKey macedPublicKey;
     std::vector<uint8_t> attestationKey;
-    result = rpc->generateEcdsaP256KeyPair(/*testMode=*/true, &macedPublicKey, &attestationKey);
+    // Start by RPC version 3, we don't support testMode=true. So just verify testMode=false here.
+    result = rpc->generateEcdsaP256KeyPair(/*testMode=*/false, &macedPublicKey, &attestationKey);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
 
     optional<vector<vector<uint8_t>>> remotelyProvisionedCertChain =
diff --git a/tv/input/aidl/android/hardware/tv/input/ITvInputCallback.aidl b/tv/input/aidl/android/hardware/tv/input/ITvInputCallback.aidl
index 5d47317..2c7e32f 100644
--- a/tv/input/aidl/android/hardware/tv/input/ITvInputCallback.aidl
+++ b/tv/input/aidl/android/hardware/tv/input/ITvInputCallback.aidl
@@ -30,7 +30,14 @@
     void notify(in TvInputEvent event);
     /**
      * Notifies the client that an TV message event has occurred. For possible event types,
-     * check TvMessageEventType.
+     * check {@link android.hardware.tv.input.TvMessageEventType}.
+     *
+     * The first message in a list of messages contained in a
+     * {@link android.hardware.tv.input.TvMessageEvent} should always have a
+     * {@link android.hardware.tv.input.TvMessage#subType} of "device_id",
+     * otherwise the event is discarded. When the subType of a message is "device_id", the ID of
+     * the device that sent the message should be contained in
+     * {@link android.hardware.tv.input.TvMessage#groupId}
      *
      * @param event Event passed to the client.
      */
diff --git a/tv/input/aidl/android/hardware/tv/input/TvMessage.aidl b/tv/input/aidl/android/hardware/tv/input/TvMessage.aidl
index 88da538..afa48a9 100644
--- a/tv/input/aidl/android/hardware/tv/input/TvMessage.aidl
+++ b/tv/input/aidl/android/hardware/tv/input/TvMessage.aidl
@@ -23,8 +23,13 @@
      */
     const long NO_GROUP_ID = -1;
     /**
-     * Extended data type, like “ATSC A/336 Watermark”, “ATSC_CC”, etc. This is opaque
-     * to the framework.
+     * Extended data type, like “ATSC A/336 Watermark”, “ATSC_CC”, etc. This type is opaque to the
+     * framework except when the subtype is "device_id". If the subtype is "device_id", the ID of
+     * device that sent the message should be contained in {@link #groupId}.
+     *
+     * The first message in a list of messages contained in
+     * {@link android.hardware.tv.input.TvMessageEvent} should always have the subtype "device_id",
+     * otherwise the event is discarded.
      */
     String subType;
     /**
@@ -32,6 +37,9 @@
      * headers and bodies of the same event. For messages that do not have a group, this value
      * should be -1.
      *
+     * If {@link #subType} is "device_id", this value should contain the ID of the device that sent
+     * this message.
+     *
      * As -1 is a reserved value, -1 should not be used as a valid groupId.
      */
     long groupId;
diff --git a/tv/input/aidl/default/TvInput.cpp b/tv/input/aidl/default/TvInput.cpp
index c986ef1..2ee8bcf 100644
--- a/tv/input/aidl/default/TvInput.cpp
+++ b/tv/input/aidl/default/TvInput.cpp
@@ -68,7 +68,13 @@
 ::ndk::ScopedAStatus TvInput::setTvMessageEnabled(int32_t deviceId, int32_t streamId,
                                                   TvMessageEventType in_type, bool enabled) {
     ALOGV("%s", __FUNCTION__);
-    // TODO: Implement this
+
+    if (mStreamConfigs.count(deviceId) == 0) {
+        ALOGW("Device with id %d isn't available", deviceId);
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
+    }
+
+    mTvMessageEventEnabled[deviceId][streamId][in_type] = enabled;
     return ::ndk::ScopedAStatus::ok();
 }
 
@@ -76,7 +82,10 @@
         MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue, int32_t in_deviceId,
         int32_t in_streamId) {
     ALOGV("%s", __FUNCTION__);
-    // TODO: Implement this
+    if (mStreamConfigs.count(in_deviceId) == 0) {
+        ALOGW("Device with id %d isn't available", in_deviceId);
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
+    }
     return ::ndk::ScopedAStatus::ok();
 }
 
diff --git a/tv/input/aidl/default/TvInput.h b/tv/input/aidl/default/TvInput.h
index 92e7d4c..5776961 100644
--- a/tv/input/aidl/default/TvInput.h
+++ b/tv/input/aidl/default/TvInput.h
@@ -22,6 +22,7 @@
 #include <aidl/android/hardware/tv/input/TvMessageEventType.h>
 #include <fmq/AidlMessageQueue.h>
 #include <map>
+#include <unordered_map>
 #include "TvInputDeviceInfoWrapper.h"
 #include "TvStreamConfigWrapper.h"
 
@@ -38,6 +39,9 @@
 namespace tv {
 namespace input {
 
+using TvMessageEnabledMap = std::unordered_map<
+        int32_t, std::unordered_map<int32_t, std::unordered_map<TvMessageEventType, bool>>>;
+
 class TvInput : public BnTvInput {
   public:
     TvInput();
@@ -53,7 +57,6 @@
     ::ndk::ScopedAStatus openStream(int32_t in_deviceId, int32_t in_streamId,
                                     NativeHandle* _aidl_return) override;
     ::ndk::ScopedAStatus closeStream(int32_t in_deviceId, int32_t in_streamId) override;
-
     void init();
 
   private:
@@ -62,6 +65,7 @@
     shared_ptr<ITvInputCallback> mCallback;
     map<int32_t, shared_ptr<TvInputDeviceInfoWrapper>> mDeviceInfos;
     map<int32_t, map<int32_t, shared_ptr<TvStreamConfigWrapper>>> mStreamConfigs;
+    TvMessageEnabledMap mTvMessageEventEnabled;
 };
 
 }  // namespace input
diff --git a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
index a2415b4..6433305 100644
--- a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
+++ b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
@@ -259,8 +259,11 @@
         return;
     }
     int32_t device_id = stream_config_.keyAt(indices[0]);
-    int32_t stream_id = stream_config_.valueAt(indices[0])[0].streamId;
-
+    vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
+    if (streamConfigs.empty()) {
+        return;
+    }
+    int32_t stream_id = streamConfigs[0].streamId;
     NativeHandle handle;
 
     ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
@@ -291,7 +294,11 @@
         return;
     }
     int32_t device_id = stream_config_.keyAt(indices[0]);
-    int32_t stream_id = stream_config_.valueAt(indices[0])[0].streamId;
+    vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
+    if (streamConfigs.empty()) {
+        return;
+    }
+    int32_t stream_id = streamConfigs[0].streamId;
 
     ALOGD("CloseStreamBeforeOpenTest: close stream, device_id=%d, stream_id=%d", device_id,
           stream_id);
@@ -299,6 +306,43 @@
                 ITvInput::STATUS_INVALID_STATE);
 }
 
+TEST_P(TvInputAidlTest, SetTvMessageEnabledTest) {
+    unique_lock<mutex> lock(mutex_);
+
+    updateAllStreamConfigurations();
+    vector<size_t> indices = getConfigIndices();
+    if (indices.empty()) {
+        return;
+    }
+    int32_t device_id = stream_config_.keyAt(indices[0]);
+    vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
+    if (streamConfigs.empty()) {
+        return;
+    }
+    int32_t stream_id = streamConfigs[0].streamId;
+    ALOGD("SetTvMessageEnabledTest: device_id=%d, stream_id=%d", device_id, stream_id);
+    tv_input_->setTvMessageEnabled(device_id, stream_id, TvMessageEventType::WATERMARK, true);
+}
+
+TEST_P(TvInputAidlTest, GetTvMessageQueueTest) {
+    unique_lock<mutex> lock(mutex_);
+
+    updateAllStreamConfigurations();
+    vector<size_t> indices = getConfigIndices();
+    if (indices.empty()) {
+        return;
+    }
+    int32_t device_id = stream_config_.keyAt(indices[0]);
+    vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
+    if (streamConfigs.empty()) {
+        return;
+    }
+    int32_t stream_id = streamConfigs[0].streamId;
+    ALOGD("GetTvMessageQueueTest: device_id=%d, stream_id=%d", device_id, stream_id);
+    MQDescriptor<int8_t, SynchronizedReadWrite> queue;
+    tv_input_->getTvMessageQueueDesc(&queue, device_id, stream_id);
+}
+
 INSTANTIATE_TEST_SUITE_P(PerInstance, TvInputAidlTest,
                          testing::ValuesIn(android::getAidlHalInstanceNames(ITvInput::descriptor)),
                          android::PrintInstanceNameToString);
diff --git a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.h b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.h
index 20d9227..832b27c 100644
--- a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.h
+++ b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.h
@@ -37,6 +37,7 @@
 using namespace std;
 using ::aidl::android::hardware::common::NativeHandle;
 using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
 using ::android::AidlMessageQueue;
 
 #define WAIT_FOR_EVENT_TIMEOUT 5