Merge changes from topic "60ghz-3-google-hal-60ghz"

* changes:
  Wifi: support 60GHz (Wigig) band
  Wifi: add new chip capability WIGIG
diff --git a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
index ff08066..3e29206 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -17,6 +17,7 @@
 #ifndef SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
 #define SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
 
+#include <functional>
 #include <vector>
 
 #include <keymasterV4_0/keymaster_tags.h>
@@ -165,11 +166,12 @@
      */
     bool Contains(Tag tag) const { return find(tag) != -1; }
 
-    template <TagType tag_type, Tag tag, typename ValueT>
-    bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
+    template <TagType tag_type, Tag tag, typename ValueT, typename Comparator = std::equal_to<>>
+    bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value,
+                  Comparator cmp = Comparator()) const {
         for (const auto& param : data_) {
             auto entry = authorizationValue(ttag, param);
-            if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
+            if (entry.isOk() && cmp(static_cast<ValueT>(entry.value()), value)) return true;
         }
         return false;
     }
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index ecc5fce..f196928 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -17,9 +17,12 @@
 #define LOG_TAG "keymaster_hidl_hal_test"
 #include <cutils/log.h>
 
-#include <iostream>
 #include <signal.h>
 
+#include <functional>
+#include <iostream>
+#include <string>
+
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/x509.h>
@@ -32,6 +35,8 @@
 
 #include "KeymasterHidlTest.h"
 
+using namespace std::string_literals;
+
 static bool arm_deleteAllKeys = false;
 static bool dump_Attestations = false;
 
@@ -315,6 +320,12 @@
     return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
 }
 
+bool is_gsi() {
+    char property_value[PROPERTY_VALUE_MAX] = {};
+    EXPECT_NE(property_get("ro.product.system.name", property_value, ""), 0);
+    return "mainline"s == property_value;
+}
+
 }  // namespace
 
 bool verify_attestation_record(const string& challenge, const string& app_id,
@@ -512,9 +523,25 @@
         EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
             << "OS version is " << os_version() << " key reported "
             << auths.GetTagValue(TAG_OS_VERSION);
-        EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
-            << "OS patch level is " << os_patch_level() << " key reported "
-            << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+
+        if (is_gsi()) {
+            // In general, TAG_OS_PATCHLEVEL should be equal to os_patch_level()
+            // reported from the system.img in use. But it is allowed to boot a
+            // GSI system.img with newer patch level, which means TAG_OS_PATCHLEVEL
+            // might be less than or equal to os_patch_level() in this case.
+            EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL,  // vbmeta.img patch level
+                                       os_patch_level(),   // system.img patch level
+                                       std::less_equal<>()))
+                    << "OS patch level is " << os_patch_level()
+                    << ", which is less than key reported " << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+        } else {
+            EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL,  // vbmeta.img patch level
+                                       os_patch_level(),   // system.img patch level
+                                       std::equal_to<>()))
+                    << "OS patch level is " << os_patch_level()
+                    << ", which is not equal to key reported "
+                    << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+        }
     }
 
     void CheckCharacteristics(const HidlBuf& key_blob,
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/IPowerStats.aidl b/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/IPowerStats.aidl
index b13f0c7..6772f6f 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/IPowerStats.aidl
+++ b/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/IPowerStats.aidl
@@ -20,12 +20,6 @@
 interface IPowerStats {
   android.hardware.powerstats.EnergyData[] getEnergyData(in int[] railIndices);
   android.hardware.powerstats.PowerEntityInfo[] getPowerEntityInfo();
-  android.hardware.powerstats.PowerEntityStateSpace[] getPowerEntityStateInfo(in int[] powerEntityIds);
   android.hardware.powerstats.PowerEntityStateResidencyResult[] getPowerEntityStateResidencyData(in int[] powerEntityIds);
   android.hardware.powerstats.RailInfo[] getRailInfo();
-  const int SUCCESS = 0;
-  const int NOT_SUPPORTED = 1;
-  const int INVALID_INPUT = 2;
-  const int FILESYSTEM_ERROR = 3;
-  const int INSUFFICIENT_RESOURCES = 4;
 }
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityInfo.aidl b/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityInfo.aidl
index 8cacd55..016af91 100644
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityInfo.aidl
+++ b/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityInfo.aidl
@@ -20,5 +20,5 @@
 parcelable PowerEntityInfo {
   int powerEntityId;
   String powerEntityName;
-  android.hardware.powerstats.PowerEntityType type;
+  android.hardware.powerstats.PowerEntityStateInfo[] states;
 }
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateSpace.aidl b/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateSpace.aidl
deleted file mode 100644
index 0508fea..0000000
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityStateSpace.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
-//
-// You must not make a backward incompatible changes to the AIDL files built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// 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.powerstats;
-@VintfStability
-parcelable PowerEntityStateSpace {
-  int powerEntityId;
-  android.hardware.powerstats.PowerEntityStateInfo[] states;
-}
diff --git a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityType.aidl b/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityType.aidl
deleted file mode 100644
index 5deefa9..0000000
--- a/powerstats/aidl/aidl_api/android.hardware.powerstats/current/android/hardware/powerstats/PowerEntityType.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
-//
-// You must not make a backward incompatible changes to the AIDL files built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// 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.powerstats;
-@Backing(type="int") @VintfStability
-enum PowerEntityType {
-  SUBSYSTEM = 0,
-  PERIPHERAL = 1,
-  POWER_DOMAIN = 2,
-}
diff --git a/powerstats/aidl/android/hardware/powerstats/IPowerStats.aidl b/powerstats/aidl/android/hardware/powerstats/IPowerStats.aidl
index f8f69e0..93d1448 100644
--- a/powerstats/aidl/android/hardware/powerstats/IPowerStats.aidl
+++ b/powerstats/aidl/android/hardware/powerstats/IPowerStats.aidl
@@ -19,17 +19,10 @@
 import android.hardware.powerstats.EnergyData;
 import android.hardware.powerstats.PowerEntityInfo;
 import android.hardware.powerstats.PowerEntityStateResidencyResult;
-import android.hardware.powerstats.PowerEntityStateSpace;
 import android.hardware.powerstats.RailInfo;
 
 @VintfStability
 interface IPowerStats {
-    const int SUCCESS = 0;
-    const int NOT_SUPPORTED = 1;
-    const int INVALID_INPUT = 2;
-    const int FILESYSTEM_ERROR = 3;
-    const int INSUFFICIENT_RESOURCES = 4;
-
     /**
      * Rail level energy measurements for low frequency clients:
      * Reports accumulated energy since boot on each rail.
@@ -53,21 +46,6 @@
     PowerEntityInfo[] getPowerEntityInfo();
 
     /**
-     * PowerEntity state information:
-     * Reports the set of power states for which the specified
-     * PowerEntity(s) provide residency data.
-     *
-     * @param powerEntityIds collection of IDs of PowerEntity(s) for which
-     *     state information is requested. PowerEntity name to ID mapping may
-     *     be queried from getPowerEntityInfo(). To get state space
-     *     information for all PowerEntity(s) pass an empty vector.
-     *
-     * @return PowerEntity state space information for
-     *     each specified PowerEntity that provides state space information.
-     */
-    PowerEntityStateSpace[] getPowerEntityStateInfo(in int[] powerEntityIds);
-
-    /**
      * PowerEntity residencies for low frequency clients:
      * Reports accumulated residency data for each specified PowerEntity.
      * Each PowerEntity may reside in one of multiple states. It may also
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityInfo.aidl b/powerstats/aidl/android/hardware/powerstats/PowerEntityInfo.aidl
index 2b5b352..72222a6 100644
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityInfo.aidl
+++ b/powerstats/aidl/android/hardware/powerstats/PowerEntityInfo.aidl
@@ -16,7 +16,7 @@
 
 package android.hardware.powerstats;
 
-import android.hardware.powerstats.PowerEntityType;
+import android.hardware.powerstats.PowerEntityStateInfo;
 
 /**
  * PowerEntityInfo contains information, such as the ID, name, and type of a
@@ -33,7 +33,7 @@
      */
     String powerEntityName;
     /**
-     * Type of the PowerEntity
+     * List of states that the PowerEntity may reside in
      */
-    PowerEntityType type;
+    PowerEntityStateInfo[] states;
 }
\ No newline at end of file
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateSpace.aidl b/powerstats/aidl/android/hardware/powerstats/PowerEntityStateSpace.aidl
deleted file mode 100644
index 8e30665..0000000
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityStateSpace.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.powerstats;
-
-import android.hardware.powerstats.PowerEntityStateInfo;
-
-/**
- * PowerEntityStateSpace contains the state space information of a given
- * PowerEntity. The state space, is the set of possible states that a given
- * PowerEntity provides residency data for.
- */
-@VintfStability
-parcelable PowerEntityStateSpace {
-    /**
-     * Unique ID of the corresponding PowerEntity
-     */
-    int powerEntityId;
-    /**
-     * List of states that the PowerEntity may reside in
-     */
-    PowerEntityStateInfo[] states;
-}
-
diff --git a/powerstats/aidl/android/hardware/powerstats/PowerEntityType.aidl b/powerstats/aidl/android/hardware/powerstats/PowerEntityType.aidl
deleted file mode 100644
index a8cd0b7..0000000
--- a/powerstats/aidl/android/hardware/powerstats/PowerEntityType.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.powerstats;
-
-@VintfStability
-@Backing(type="int")
-enum PowerEntityType {
-    /**
-     * A subsystem is a self-contained compute unit. Some examples include
-     * application processor, DSP, GPU.
-     */
-    SUBSYSTEM = 0,
-    /**
-     * A peripheral is an auxiliary device that connects to and works with a
-     * compute unit. Some examples include simple sensors, camera, display.
-     */
-    PERIPHERAL = 1,
-    /**
-     * A power domain is a single subsystem or a collection of subsystems
-     * that is controlled by a single voltage rail.
-     */
-    POWER_DOMAIN = 2,
-}
\ No newline at end of file
diff --git a/powerstats/aidl/default/PowerStats.cpp b/powerstats/aidl/default/PowerStats.cpp
index 50a829e..8d6a0ee 100644
--- a/powerstats/aidl/default/PowerStats.cpp
+++ b/powerstats/aidl/default/PowerStats.cpp
@@ -34,13 +34,7 @@
     (void)_aidl_return;
     return ndk::ScopedAStatus::ok();
 }
-ndk::ScopedAStatus PowerStats::getPowerEntityStateInfo(
-        const std::vector<int32_t>& in_powerEntityIds,
-        std::vector<PowerEntityStateSpace>* _aidl_return) {
-    (void)in_powerEntityIds;
-    (void)_aidl_return;
-    return ndk::ScopedAStatus::ok();
-}
+
 ndk::ScopedAStatus PowerStats::getPowerEntityStateResidencyData(
         const std::vector<int32_t>& in_powerEntityIds,
         std::vector<PowerEntityStateResidencyResult>* _aidl_return) {
@@ -48,6 +42,7 @@
     (void)_aidl_return;
     return ndk::ScopedAStatus::ok();
 }
+
 ndk::ScopedAStatus PowerStats::getRailInfo(std::vector<RailInfo>* _aidl_return) {
     (void)_aidl_return;
     return ndk::ScopedAStatus::ok();
diff --git a/powerstats/aidl/default/PowerStats.h b/powerstats/aidl/default/PowerStats.h
index 392d1e6..49240cb 100644
--- a/powerstats/aidl/default/PowerStats.h
+++ b/powerstats/aidl/default/PowerStats.h
@@ -29,9 +29,6 @@
     ndk::ScopedAStatus getEnergyData(const std::vector<int32_t>& in_railIndices,
                                      std::vector<EnergyData>* _aidl_return) override;
     ndk::ScopedAStatus getPowerEntityInfo(std::vector<PowerEntityInfo>* _aidl_return) override;
-    ndk::ScopedAStatus getPowerEntityStateInfo(
-            const std::vector<int32_t>& in_powerEntityIds,
-            std::vector<PowerEntityStateSpace>* _aidl_return) override;
     ndk::ScopedAStatus getPowerEntityStateResidencyData(
             const std::vector<int32_t>& in_powerEntityIds,
             std::vector<PowerEntityStateResidencyResult>* _aidl_return) override;
diff --git a/powerstats/aidl/vts/VtsHalPowerStatsTargetTest.cpp b/powerstats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
index fc0e659..b3cd233 100644
--- a/powerstats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
+++ b/powerstats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
@@ -25,7 +25,6 @@
 using aidl::android::hardware::powerstats::IPowerStats;
 using aidl::android::hardware::powerstats::PowerEntityInfo;
 using aidl::android::hardware::powerstats::PowerEntityStateResidencyResult;
-using aidl::android::hardware::powerstats::PowerEntityStateSpace;
 using aidl::android::hardware::powerstats::RailInfo;
 using ndk::SpAIBinder;
 
@@ -45,14 +44,74 @@
     ASSERT_TRUE(powerstats->getEnergyData({}, &data).isOk());
 }
 
-TEST_P(PowerStatsAidl, TestGetPowerEntityInfo) {
-    std::vector<PowerEntityInfo> info;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&info).isOk());
+// Each PowerEntity must have a valid name
+TEST_P(PowerStatsAidl, ValidatePowerEntityNames) {
+    std::vector<PowerEntityInfo> infos;
+    ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
+
+    for (auto info : infos) {
+        EXPECT_NE(info.powerEntityName, "");
+    }
 }
 
-TEST_P(PowerStatsAidl, TestGetPowerEntityStateInfo) {
-    std::vector<PowerEntityStateSpace> info;
-    ASSERT_TRUE(powerstats->getPowerEntityStateInfo({}, &info).isOk());
+// Each power entity must have a unique name
+TEST_P(PowerStatsAidl, ValidatePowerEntityUniqueNames) {
+    std::vector<PowerEntityInfo> infos;
+    ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
+
+    std::set<std::string> names;
+    for (auto info : infos) {
+        EXPECT_TRUE(names.insert(info.powerEntityName).second);
+    }
+}
+
+// Each PowerEntity must have a unique ID
+TEST_P(PowerStatsAidl, ValidatePowerEntityIds) {
+    std::vector<PowerEntityInfo> infos;
+    ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
+
+    std::set<int32_t> ids;
+    for (auto info : infos) {
+        EXPECT_TRUE(ids.insert(info.powerEntityId).second);
+    }
+}
+
+// Each state must have a valid name
+TEST_P(PowerStatsAidl, ValidateStateNames) {
+    std::vector<PowerEntityInfo> infos;
+    ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
+
+    for (auto info : infos) {
+        for (auto state : info.states) {
+            EXPECT_NE(state.powerEntityStateName, "");
+        }
+    }
+}
+
+// Each state must have a name that is unique to the given PowerEntity
+TEST_P(PowerStatsAidl, ValidateStateUniqueNames) {
+    std::vector<PowerEntityInfo> infos;
+    ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
+
+    for (auto info : infos) {
+        std::set<std::string> stateNames;
+        for (auto state : info.states) {
+            EXPECT_TRUE(stateNames.insert(state.powerEntityStateName).second);
+        }
+    }
+}
+
+// Each state must have an ID that is unique to the given PowerEntity
+TEST_P(PowerStatsAidl, ValidateStateUniqueIds) {
+    std::vector<PowerEntityInfo> infos;
+    ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
+
+    for (auto info : infos) {
+        std::set<uint32_t> stateIds;
+        for (auto state : info.states) {
+            EXPECT_TRUE(stateIds.insert(state.powerEntityStateId).second);
+        }
+    }
 }
 
 TEST_P(PowerStatsAidl, TestGetPowerEntityStateResidencyData) {
diff --git a/tests/msgq/1.0/default/Android.bp b/tests/msgq/1.0/default/Android.bp
index 47b8df1..a5ba23d 100644
--- a/tests/msgq/1.0/default/Android.bp
+++ b/tests/msgq/1.0/default/Android.bp
@@ -70,6 +70,17 @@
         "libbinder_ndk",
     ],
 
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+    test_suites: ["device-tests"],
+
     // Allow dlsym'ing self for statically linked passthrough implementations
     ldflags: ["-rdynamic"],
 
@@ -84,5 +95,4 @@
         "android.hardware.tests.msgq@1.0-impl",
         "android.fmq.test-impl",
     ],
-    test_suites: ["general-tests"],
 }
diff --git a/tv/tuner/1.1/IFrontend.hal b/tv/tuner/1.1/IFrontend.hal
index b570549..0b0ce39 100644
--- a/tv/tuner/1.1/IFrontend.hal
+++ b/tv/tuner/1.1/IFrontend.hal
@@ -67,4 +67,18 @@
      */
     scan_1_1(FrontendSettings settings, FrontendScanType type, FrontendSettingsExt settingsExt)
             generates (Result result);
+
+    /**
+     * Link Conditional Access Modules (CAM) to Frontend support Common Interface (CI) bypass mode.
+     *
+     * The client may use this to link CI-CAM to a frontend. CI bypass mode requires that the
+     * CICAM also receives the TS concurrently from the frontend when the Demux is receiving the TS
+     * directly from the frontend.
+     *
+     * @param ciCamId specify CI-CAM Id to link.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    linkCiCam(uint32_t ciCamId) generates (Result result);
 };
diff --git a/tv/tuner/1.1/default/Frontend.cpp b/tv/tuner/1.1/default/Frontend.cpp
index 1e9435b..467d547 100644
--- a/tv/tuner/1.1/default/Frontend.cpp
+++ b/tv/tuner/1.1/default/Frontend.cpp
@@ -273,6 +273,14 @@
     return Result::SUCCESS;
 }
 
+Return<Result> Frontend::linkCiCam(uint32_t ciCamId) {
+    ALOGV("%s", __FUNCTION__);
+
+    mCiCamId = ciCamId;
+
+    return Result::SUCCESS;
+}
+
 FrontendType Frontend::getFrontendType() {
     return mType;
 }
diff --git a/tv/tuner/1.1/default/Frontend.h b/tv/tuner/1.1/default/Frontend.h
index d44f4ae..6a80232 100644
--- a/tv/tuner/1.1/default/Frontend.h
+++ b/tv/tuner/1.1/default/Frontend.h
@@ -62,6 +62,8 @@
 
     virtual Return<Result> setLnb(uint32_t lnb) override;
 
+    virtual Return<Result> linkCiCam(uint32_t ciCamId) override;
+
     FrontendType getFrontendType();
 
     FrontendId getFrontendId();
@@ -78,6 +80,7 @@
     FrontendType mType = FrontendType::UNDEFINED;
     FrontendId mId = 0;
     bool mIsLocked = false;
+    uint32_t mCiCamId;
 
     std::ifstream mFrontendData;
 };