cas: add CAS hal
Add CAS hal definitions and default service implementation.
bug: 22804304
Change-Id: I0a89608fe75c5f3c5e6888f9b771305742760707
diff --git a/cas/1.0/Android.bp b/cas/1.0/Android.bp
new file mode 100644
index 0000000..2251f11
--- /dev/null
+++ b/cas/1.0/Android.bp
@@ -0,0 +1,84 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+ name: "android.hardware.cas@1.0_hal",
+ srcs: [
+ "types.hal",
+ "ICas.hal",
+ "ICasListener.hal",
+ "IDescramblerBase.hal",
+ "IMediaCasService.hal",
+ ],
+}
+
+genrule {
+ name: "android.hardware.cas@1.0_genc++",
+ tools: ["hidl-gen"],
+ cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas@1.0",
+ srcs: [
+ ":android.hardware.cas@1.0_hal",
+ ],
+ out: [
+ "android/hardware/cas/1.0/types.cpp",
+ "android/hardware/cas/1.0/CasAll.cpp",
+ "android/hardware/cas/1.0/CasListenerAll.cpp",
+ "android/hardware/cas/1.0/DescramblerBaseAll.cpp",
+ "android/hardware/cas/1.0/MediaCasServiceAll.cpp",
+ ],
+}
+
+genrule {
+ name: "android.hardware.cas@1.0_genc++_headers",
+ tools: ["hidl-gen"],
+ cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas@1.0",
+ srcs: [
+ ":android.hardware.cas@1.0_hal",
+ ],
+ out: [
+ "android/hardware/cas/1.0/types.h",
+ "android/hardware/cas/1.0/hwtypes.h",
+ "android/hardware/cas/1.0/ICas.h",
+ "android/hardware/cas/1.0/IHwCas.h",
+ "android/hardware/cas/1.0/BnHwCas.h",
+ "android/hardware/cas/1.0/BpHwCas.h",
+ "android/hardware/cas/1.0/BsCas.h",
+ "android/hardware/cas/1.0/ICasListener.h",
+ "android/hardware/cas/1.0/IHwCasListener.h",
+ "android/hardware/cas/1.0/BnHwCasListener.h",
+ "android/hardware/cas/1.0/BpHwCasListener.h",
+ "android/hardware/cas/1.0/BsCasListener.h",
+ "android/hardware/cas/1.0/IDescramblerBase.h",
+ "android/hardware/cas/1.0/IHwDescramblerBase.h",
+ "android/hardware/cas/1.0/BnHwDescramblerBase.h",
+ "android/hardware/cas/1.0/BpHwDescramblerBase.h",
+ "android/hardware/cas/1.0/BsDescramblerBase.h",
+ "android/hardware/cas/1.0/IMediaCasService.h",
+ "android/hardware/cas/1.0/IHwMediaCasService.h",
+ "android/hardware/cas/1.0/BnHwMediaCasService.h",
+ "android/hardware/cas/1.0/BpHwMediaCasService.h",
+ "android/hardware/cas/1.0/BsMediaCasService.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.cas@1.0",
+ defaults: ["hidl-module-defaults"],
+ generated_sources: ["android.hardware.cas@1.0_genc++"],
+ generated_headers: ["android.hardware.cas@1.0_genc++_headers"],
+ export_generated_headers: ["android.hardware.cas@1.0_genc++_headers"],
+ vendor_available: true,
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ "libcutils",
+ ],
+ export_shared_lib_headers: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "libutils",
+ ],
+}
diff --git a/cas/1.0/CasHal.mk b/cas/1.0/CasHal.mk
new file mode 100644
index 0000000..3cae6bf
--- /dev/null
+++ b/cas/1.0/CasHal.mk
@@ -0,0 +1,192 @@
+#
+# Copyright (C) 2017 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.
+
+
+########################################################################
+# Included by frameworks/base for MediaCas. Hidl HAL can't be linked as
+# Java lib from frameworks because it has dependency on frameworks itself.
+#
+
+intermediates := $(TARGET_OUT_COMMON_GEN)/JAVA_LIBRARIES/android.hardware.cas-V1.0-java_intermediates
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+HIDL_PATH := system/libhidl/transport/base/1.0
+
+#
+# Build types.hal (DebugInfo)
+#
+GEN := $(intermediates)/android/hidl/base/V1_0/DebugInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hidl:system/libhidl/transport \
+ android.hidl.base@1.0::types.DebugInfo
+
+$(GEN): $(HIDL_PATH)/types.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IBase.hal
+#
+GEN := $(intermediates)/android/hidl/base/V1_0/IBase.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hidl:system/libhidl/transport \
+ android.hidl.base@1.0::IBase
+
+$(GEN): $(HIDL_PATH)/IBase.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+HIDL_PATH := hardware/interfaces/cas/1.0
+
+#
+# Build types.hal (HidlCasPluginDescriptor)
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/HidlCasPluginDescriptor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.cas@1.0::types.HidlCasPluginDescriptor
+
+$(GEN): $(HIDL_PATH)/types.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.cas@1.0::types.Status
+
+$(GEN): $(HIDL_PATH)/types.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ICas.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/ICas.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/ICas.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.cas@1.0::ICas
+
+$(GEN): $(HIDL_PATH)/ICas.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ICasListener.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/ICasListener.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/ICasListener.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.cas@1.0::ICasListener
+
+$(GEN): $(HIDL_PATH)/ICasListener.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IDescramblerBase.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/IDescramblerBase.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.cas@1.0::IDescramblerBase
+
+$(GEN): $(HIDL_PATH)/IDescramblerBase.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IMediaCasService.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/IMediaCasService.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IMediaCasService.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/ICas.hal
+$(GEN): $(HIDL_PATH)/ICas.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/ICasListener.hal
+$(GEN): $(HIDL_PATH)/ICasListener.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.cas@1.0::IMediaCasService
+
+$(GEN): $(HIDL_PATH)/IMediaCasService.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
diff --git a/cas/1.0/ICas.hal b/cas/1.0/ICas.hal
new file mode 100644
index 0000000..08a92da
--- /dev/null
+++ b/cas/1.0/ICas.hal
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2017 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.cas@1.0;
+
+import android.hardware.cas@1.0::types;
+
+/**
+ * ICas is the API to control the cas system and is accessible from both
+ * Java and native level. It is used to manage sessions, provision/refresh
+ * the cas system, and process the EMM/ECM messages. It also allows bi-directional,
+ * scheme-specific communications between the client and the cas system.
+ */
+
+interface ICas {
+ /**
+ * Provide the CA private data from a CA_descriptor in the conditional
+ * access table to a CasPlugin.
+ *
+ * @param pvtData a byte array containing the private data, the format of
+ * which is scheme-specific and opaque to the framework.
+ * @return status the status of the call.
+ */
+ setPrivateData(vec<uint8_t> pvtData) generates (Status status);
+
+ /**
+ * Open a session to descramble one or more streams scrambled by the
+ * conditional access system.
+ *
+ * @return status the status of the call.
+ * @return sessionId the id of the newly opened session.
+ */
+ openSession() generates(Status status, HidlCasSessionId sessionId);
+
+ /**
+ * Close a session.
+ *
+ * @param sessionId the id of the session to be closed.
+ * @return status the status of the call.
+ */
+ closeSession(HidlCasSessionId sessionId) generates (Status status);
+
+ /**
+ * Provide the CA private data from a CA_descriptor in the program map
+ * table to a session.
+ *
+ * @param sessionId the id of the session which the private data applies to.
+ * @param pvtData a byte array containing the private data, the format of
+ * which is scheme-specific and opaque to the framework.
+ * @return status the status of the call.
+ */
+ setSessionPrivateData(HidlCasSessionId sessionId, vec<uint8_t> pvtData)
+ generates (Status status);
+
+ /**
+ * Process an ECM from the ECM stream for this session’s elementary stream.
+ *
+ * @param sessionId the id of the session which the ecm data applies to.
+ * @param ecm a byte array containing the ecm data.
+ * @return status the status of the call.
+ */
+ processEcm(HidlCasSessionId sessionId, vec<uint8_t> ecm)
+ generates (Status status);
+
+ /**
+ * Process an in-band EMM from the EMM stream.
+ *
+ * @param emm a byte array containing the emm data.
+ * @return status the status of the call.
+ */
+ processEmm(vec<uint8_t> emm) generates (Status status);
+
+ /**
+ * Send an scheme-specific event to the CasPlugin.
+ *
+ * @param event an integer denoting a scheme-specific event to be sent.
+ * @param arg a scheme-specific integer argument for the event.
+ * @param data a byte array containing scheme-specific data for the event.
+ * @return status the status of the call.
+ */
+ sendEvent(int32_t event, int32_t arg, vec<uint8_t> eventData)
+ generates (Status status);
+
+ /**
+ * Initiate a provisioning operation for a CA system.
+ *
+ * @param provisionString string containing information needed for the
+ * provisioning operation, the format of which is scheme and implementation
+ * specific.
+ * @return status the status of the call.
+ */
+ provision(string provisionString) generates (Status status);
+
+ /**
+ * Notify the CA system to refresh entitlement keys.
+ *
+ * @param refreshType the type of the refreshment.
+ * @param refreshData private data associated with the refreshment.
+ * @return status the status of the call.
+ */
+ refreshEntitlements(int32_t refreshType, vec<uint8_t> refreshData)
+ generates (Status status);
+
+ /**
+ * Release the descrambler instance.
+ *
+ * @return status the status of the call.
+ */
+ release() generates (Status status);
+};
diff --git a/cas/1.0/ICasListener.hal b/cas/1.0/ICasListener.hal
new file mode 100644
index 0000000..8ae6014
--- /dev/null
+++ b/cas/1.0/ICasListener.hal
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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.cas@1.0;
+
+interface ICasListener {
+ /**
+ * Notify the listener of a scheme-specific event from the CA system.
+ *
+ * @param event an integer whose meaning is scheme-specific.
+ * @param arg an integer whose meaning is scheme-specific.
+ * @param data a byte array of data whose format and meaning are
+ * scheme-specific.
+ */
+ onEvent(int32_t event, int32_t arg, vec<uint8_t> data);
+};
diff --git a/cas/1.0/IDescramblerBase.hal b/cas/1.0/IDescramblerBase.hal
new file mode 100644
index 0000000..a126084
--- /dev/null
+++ b/cas/1.0/IDescramblerBase.hal
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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.cas@1.0;
+
+import android.hardware.cas@1.0::types;
+
+/**
+ * IDescramblerBase is the API to control the descrambler and is accessible
+ * from both Java and native level.
+ */
+
+interface IDescramblerBase {
+ /**
+ * Associate a MediaCas session with this MediaDescrambler instance.
+ *
+ * @param sessionId the id of the session to associate with this descrambler instance.
+ * @return status the status of the call.
+ */
+ setMediaCasSession(HidlCasSessionId sessionId) generates (Status status);
+
+ /**
+ * Query if the scrambling scheme requires the use of a secure decoder
+ * to decode data of the given mime type.
+ *
+ * @param mime the mime type of the media data.
+ * @return result whether the descrambler requires a secure decoder.
+ */
+ requiresSecureDecoderComponent(string mime) generates (bool result);
+
+ /**
+ * Release the descrambler instance.
+ *
+ * @return status the status of the call.
+ */
+ release() generates (Status status);
+};
diff --git a/cas/1.0/IMediaCasService.hal b/cas/1.0/IMediaCasService.hal
new file mode 100644
index 0000000..cfeafad
--- /dev/null
+++ b/cas/1.0/IMediaCasService.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 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.cas@1.0;
+
+import android.hardware.cas@1.0::ICas;
+import android.hardware.cas@1.0::ICasListener;
+import android.hardware.cas@1.0::IDescramblerBase;
+
+/**
+ * IMediaCasService is the main entry point for interacting with a vendor's
+ * cas HAL to create cas and descrambler plugin instances. A cas plugin instance
+ * opens cas sessions which are used to obtain keys for a descrambler session,
+ * which can in turn be used to descramble protected video content.
+ */
+interface IMediaCasService {
+ /**
+ * List all available CA systems on the device.
+ *
+ * @return descriptors an array of descriptors for the available CA systems.
+ */
+ enumeratePlugins() generates (vec<HidlCasPluginDescriptor> descriptors);
+
+ /**
+ * Query if a certain CA system is supported on this device.
+ *
+ * @param CA_system_id the id of the CA system.
+ * @return result whether the specified CA system is supported on this device.
+ */
+ isSystemIdSupported(int32_t CA_system_id) generates (bool result);
+
+ /**
+ * Construct a new instance of a CasPlugin given a CA_system_id.
+ *
+ * @param CA_system_id the id of the CA system.
+ * @param listener the event listener to receive events coming from the CasPlugin.
+ * @return cas the newly created CasPlugin interface.
+ */
+ createPlugin(int32_t CA_system_id, ICasListener listener) generates (ICas cas);
+
+ /**
+ * Query if the descrambling scheme for a CA system is supported on this device.
+ *
+ * @param CA_system_id the id of the CA system.
+ * @return result whether the specified descrambling scheme is supported on this device.
+ */
+ isDescramblerSupported(int32_t CA_system_id) generates (bool result);
+
+ /**
+ * Construct a new instance of a DescramblerPlugin given a CA_system_id.
+ *
+ * @param CA_system_id the id of the CA system.
+ * @return descrambler the newly created plugin interface.
+ */
+ createDescrambler(int32_t CA_system_id) generates (IDescramblerBase descrambler);
+};
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
new file mode 100644
index 0000000..953aa37
--- /dev/null
+++ b/cas/1.0/default/Android.bp
@@ -0,0 +1,35 @@
+cc_binary {
+ name: "android.hardware.cas@1.0-service",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "CasImpl.cpp",
+ "DescramblerImpl.cpp",
+ "MediaCasService.cpp",
+ "service.cpp",
+ "SharedLibrary.cpp",
+ "TypeConvert.cpp",
+ ],
+
+ product_variables: {
+ treble: {
+ cflags: ["-DUSE_VNDBINDER"],
+ },
+ },
+
+ compile_multilib: "32",
+ init_rc: ["android.hardware.cas@1.0-service.rc"],
+
+ shared_libs: [
+ "android.hardware.cas@1.0",
+ "android.hardware.cas.native@1.0",
+ "android.hidl.memory@1.0",
+ "libbinder",
+ "libhidlbase",
+ "libhidlmemory",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/cas/1.0/default/CasImpl.cpp b/cas/1.0/default/CasImpl.cpp
new file mode 100644
index 0000000..9d1f4a3
--- /dev/null
+++ b/cas/1.0/default/CasImpl.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-CasImpl"
+
+#include <android/hardware/cas/1.0/ICasListener.h>
+#include <media/cas/CasAPI.h>
+#include <utils/Log.h>
+
+#include "CasImpl.h"
+#include "SharedLibrary.h"
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+struct CasImpl::PluginHolder : public RefBase {
+public:
+ explicit PluginHolder(CasPlugin *plugin) : mPlugin(plugin) {}
+ ~PluginHolder() { if (mPlugin != NULL) delete mPlugin; }
+ CasPlugin* get() { return mPlugin; }
+
+private:
+ CasPlugin *mPlugin;
+ DISALLOW_EVIL_CONSTRUCTORS(PluginHolder);
+};
+
+CasImpl::CasImpl(const sp<ICasListener> &listener)
+ : mPluginHolder(NULL), mListener(listener) {
+ ALOGV("CTOR");
+}
+
+CasImpl::~CasImpl() {
+ ALOGV("DTOR");
+ release();
+}
+
+//static
+void CasImpl::OnEvent(
+ void *appData,
+ int32_t event,
+ int32_t arg,
+ uint8_t *data,
+ size_t size) {
+ if (appData == NULL) {
+ ALOGE("Invalid appData!");
+ return;
+ }
+ CasImpl *casImpl = static_cast<CasImpl *>(appData);
+ casImpl->onEvent(event, arg, data, size);
+}
+
+void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin *plugin) {
+ mLibrary = library;
+ mPluginHolder = new PluginHolder(plugin);
+}
+
+void CasImpl::onEvent(
+ int32_t event, int32_t arg, uint8_t *data, size_t size) {
+ if (mListener == NULL) {
+ return;
+ }
+
+ HidlCasData eventData;
+ if (data != NULL) {
+ eventData.setToExternal(data, size);
+ }
+
+ mListener->onEvent(event, arg, eventData);
+}
+
+Return<Status> CasImpl::setPrivateData(const HidlCasData& pvtData) {
+ ALOGV("%s", __FUNCTION__);
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return toStatus(INVALID_OPERATION);
+ }
+ return toStatus(holder->get()->setPrivateData(pvtData));
+}
+
+Return<void> CasImpl::openSession(openSession_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+ CasSessionId sessionId;
+
+ sp<PluginHolder> holder = mPluginHolder;
+ status_t err = INVALID_OPERATION;
+ if (holder != NULL) {
+ err = holder->get()->openSession(&sessionId);
+ }
+
+ _hidl_cb(toStatus(err), sessionId);
+
+ return Void();
+}
+
+Return<Status> CasImpl::setSessionPrivateData(
+ const HidlCasSessionId &sessionId, const HidlCasData& pvtData) {
+ ALOGV("%s: sessionId=%s", __FUNCTION__,
+ sessionIdToString(sessionId).string());
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return toStatus(INVALID_OPERATION);
+ }
+ return toStatus(
+ holder->get()->setSessionPrivateData(
+ sessionId, pvtData));
+}
+
+Return<Status> CasImpl::closeSession(const HidlCasSessionId &sessionId) {
+ ALOGV("%s: sessionId=%s", __FUNCTION__,
+ sessionIdToString(sessionId).string());
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return toStatus(INVALID_OPERATION);
+ }
+ return toStatus(holder->get()->closeSession(sessionId));
+}
+
+Return<Status> CasImpl::processEcm(
+ const HidlCasSessionId &sessionId, const HidlCasData& ecm) {
+ ALOGV("%s: sessionId=%s", __FUNCTION__,
+ sessionIdToString(sessionId).string());
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ return toStatus(holder->get()->processEcm(sessionId, ecm));
+}
+
+Return<Status> CasImpl::processEmm(const HidlCasData& emm) {
+ ALOGV("%s", __FUNCTION__);
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ return toStatus(holder->get()->processEmm(emm));
+}
+
+Return<Status> CasImpl::sendEvent(
+ int32_t event, int32_t arg,
+ const HidlCasData& eventData) {
+ ALOGV("%s", __FUNCTION__);
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ status_t err = holder->get()->sendEvent(event, arg, eventData);
+ return toStatus(err);
+}
+
+Return<Status> CasImpl::provision(const hidl_string& provisionString) {
+ ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str());
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ return toStatus(holder->get()->provision(String8(provisionString.c_str())));
+}
+
+Return<Status> CasImpl::refreshEntitlements(
+ int32_t refreshType,
+ const HidlCasData& refreshData) {
+ ALOGV("%s", __FUNCTION__);
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ status_t err = holder->get()->refreshEntitlements(refreshType, refreshData);
+ return toStatus(err);
+}
+
+Return<Status> CasImpl::release() {
+ ALOGV("%s: plugin=%p", __FUNCTION__,
+ mPluginHolder != NULL ? mPluginHolder->get() : NULL);
+ mPluginHolder.clear();
+ return Status::OK;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/CasImpl.h b/cas/1.0/default/CasImpl.h
new file mode 100644
index 0000000..841d64e
--- /dev/null
+++ b/cas/1.0/default/CasImpl.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_CAS_IMPL_H_
+#define ANDROID_HARDWARE_CAS_V1_0_CAS_IMPL_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <android/hardware/cas/1.0/ICas.h>
+
+namespace android {
+struct CasPlugin;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+struct ICasListener;
+namespace implementation {
+
+class SharedLibrary;
+
+class CasImpl : public ICas {
+public:
+ CasImpl(const sp<ICasListener> &listener);
+ virtual ~CasImpl();
+
+ static void OnEvent(
+ void *appData,
+ int32_t event,
+ int32_t arg,
+ uint8_t *data,
+ size_t size);
+
+ void init(const sp<SharedLibrary>& library, CasPlugin *plugin);
+ void onEvent(
+ int32_t event,
+ int32_t arg,
+ uint8_t *data,
+ size_t size);
+
+ // ICas inherits
+
+ virtual Return<Status> setPrivateData(
+ const HidlCasData& pvtData) override;
+
+ virtual Return<void> openSession(
+ openSession_cb _hidl_cb) override;
+
+ virtual Return<Status> closeSession(
+ const HidlCasSessionId& sessionId) override;
+
+ virtual Return<Status> setSessionPrivateData(
+ const HidlCasSessionId& sessionId,
+ const HidlCasData& pvtData) override;
+
+ virtual Return<Status> processEcm(
+ const HidlCasSessionId& sessionId,
+ const HidlCasData& ecm) override;
+
+ virtual Return<Status> processEmm(
+ const HidlCasData& emm) override;
+
+ virtual Return<Status> sendEvent(
+ int32_t event, int32_t arg,
+ const HidlCasData& eventData) override;
+
+ virtual Return<Status> provision(
+ const hidl_string& provisionString) override;
+
+ virtual Return<Status> refreshEntitlements(
+ int32_t refreshType,
+ const HidlCasData& refreshData) override;
+
+ virtual Return<Status> release() override;
+
+private:
+ struct PluginHolder;
+ sp<SharedLibrary> mLibrary;
+ sp<PluginHolder> mPluginHolder;
+ sp<ICasListener> mListener;
+
+ DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_CAS_IMPL_H_
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp
new file mode 100644
index 0000000..3d90809
--- /dev/null
+++ b/cas/1.0/default/DescramblerImpl.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-DescramblerImpl"
+
+#include <hidlmemory/mapping.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/cas/DescramblerAPI.h>
+#include <utils/Log.h>
+
+#include "DescramblerImpl.h"
+#include "SharedLibrary.h"
+#include "TypeConvert.h"
+
+namespace android {
+using hidl::memory::V1_0::IMemory;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+#define CHECK_SUBSAMPLE_DEF(type) \
+static_assert(sizeof(SubSample) == sizeof(type::SubSample), \
+ "SubSample: size doesn't match"); \
+static_assert(offsetof(SubSample, numBytesOfClearData) \
+ == offsetof(type::SubSample, mNumBytesOfClearData), \
+ "SubSample: numBytesOfClearData offset doesn't match"); \
+static_assert(offsetof(SubSample, numBytesOfEncryptedData) \
+ == offsetof(type::SubSample, mNumBytesOfEncryptedData), \
+ "SubSample: numBytesOfEncryptedData offset doesn't match")
+
+CHECK_SUBSAMPLE_DEF(DescramblerPlugin);
+CHECK_SUBSAMPLE_DEF(CryptoPlugin);
+
+DescramblerImpl::DescramblerImpl(
+ const sp<SharedLibrary>& library, DescramblerPlugin *plugin) :
+ mLibrary(library), mPlugin(plugin) {
+ ALOGV("CTOR: mPlugin=%p", mPlugin);
+}
+
+DescramblerImpl::~DescramblerImpl() {
+ ALOGV("DTOR: mPlugin=%p", mPlugin);
+ release();
+}
+
+Return<Status> DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) {
+ ALOGV("%s: sessionId=%s", __FUNCTION__,
+ sessionIdToString(sessionId).string());
+
+ return toStatus(mPlugin->setMediaCasSession(sessionId));
+}
+
+Return<bool> DescramblerImpl::requiresSecureDecoderComponent(
+ const hidl_string& mime) {
+ return mPlugin->requiresSecureDecoderComponent(String8(mime.c_str()));
+}
+
+Return<void> DescramblerImpl::descramble(
+ ScramblingControl scramblingControl,
+ const hidl_vec<SubSample>& subSamples,
+ const SharedBuffer& srcBuffer,
+ uint64_t srcOffset,
+ const DestinationBuffer& dstBuffer,
+ uint64_t dstOffset,
+ descramble_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ sp<IMemory> srcMem = mapMemory(srcBuffer.heapBase);
+ void *srcPtr = (uint8_t *)(void *)srcMem->getPointer() + srcBuffer.offset;
+ void *dstPtr = NULL;
+ if (dstBuffer.type == BufferType::SHARED_MEMORY) {
+ // When using shared memory, src buffer is also used as dst,
+ // we don't map it again here.
+ dstPtr = srcPtr;
+ } else {
+ native_handle_t *handle = const_cast<native_handle_t *>(
+ dstBuffer.secureMemory.getNativeHandle());
+ dstPtr = static_cast<void *>(handle);
+ }
+ // Casting hidl SubSample to DescramblerPlugin::SubSample, but need
+ // to ensure structs are actually idential
+
+ int32_t result = mPlugin->descramble(
+ dstBuffer.type != BufferType::SHARED_MEMORY,
+ (DescramblerPlugin::ScramblingControl)scramblingControl,
+ subSamples.size(),
+ (DescramblerPlugin::SubSample*)subSamples.data(),
+ srcPtr,
+ srcOffset,
+ dstPtr,
+ dstOffset,
+ NULL);
+
+ _hidl_cb(toStatus(result >= 0 ? OK : result), result, NULL);
+ return Void();
+}
+
+Return<Status> DescramblerImpl::release() {
+ ALOGV("%s: mPlugin=%p", __FUNCTION__, mPlugin);
+
+ if (mPlugin != NULL) {
+ delete mPlugin;
+ mPlugin = NULL;
+ }
+ return Status::OK;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/DescramblerImpl.h b/cas/1.0/default/DescramblerImpl.h
new file mode 100644
index 0000000..d3b146e
--- /dev/null
+++ b/cas/1.0/default/DescramblerImpl.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_DESCRAMBLER_IMPL_H_
+#define ANDROID_HARDWARE_CAS_V1_0_DESCRAMBLER_IMPL_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+
+namespace android {
+struct DescramblerPlugin;
+using namespace hardware::cas::native::V1_0;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+class SharedLibrary;
+
+class DescramblerImpl : public IDescrambler {
+public:
+ DescramblerImpl(const sp<SharedLibrary>& library, DescramblerPlugin *plugin);
+ virtual ~DescramblerImpl();
+
+ virtual Return<Status> setMediaCasSession(
+ const HidlCasSessionId& sessionId) override;
+
+ virtual Return<bool> requiresSecureDecoderComponent(
+ const hidl_string& mime) override;
+
+ virtual Return<void> descramble(
+ ScramblingControl scramblingControl,
+ const hidl_vec<SubSample>& subSamples,
+ const SharedBuffer& srcBuffer,
+ uint64_t srcOffset,
+ const DestinationBuffer& dstBuffer,
+ uint64_t dstOffset,
+ descramble_cb _hidl_cb) override;
+
+ virtual Return<Status> release() override;
+
+private:
+ sp<SharedLibrary> mLibrary;
+ DescramblerPlugin *mPlugin;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_DESCRAMBLER_IMPL_H_
diff --git a/cas/1.0/default/FactoryLoader.h b/cas/1.0/default/FactoryLoader.h
new file mode 100644
index 0000000..18c2186
--- /dev/null
+++ b/cas/1.0/default/FactoryLoader.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
+#define ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include "SharedLibrary.h"
+#include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
+#include <media/cas/CasAPI.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+template <class T>
+class FactoryLoader {
+public:
+ FactoryLoader(const char *name) :
+ mFactory(NULL), mCreateFactoryFuncName(name) {}
+
+ virtual ~FactoryLoader() { closeFactory(); }
+
+ bool findFactoryForScheme(
+ int32_t CA_system_id,
+ sp<SharedLibrary> *library = NULL,
+ T** factory = NULL);
+
+ bool enumeratePlugins(vector<HidlCasPluginDescriptor>* results);
+
+private:
+ typedef T*(*CreateFactoryFunc)();
+
+ Mutex mMapLock;
+ T* mFactory;
+ const char *mCreateFactoryFuncName;
+ sp<SharedLibrary> mLibrary;
+ KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
+ KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap;
+
+ bool loadFactoryForSchemeFromPath(
+ const String8 &path,
+ int32_t CA_system_id,
+ sp<SharedLibrary> *library,
+ T** factory);
+
+ bool queryPluginsFromPath(
+ const String8 &path,
+ vector<HidlCasPluginDescriptor>* results);
+
+ bool openFactory(const String8 &path);
+ void closeFactory();
+};
+
+template <class T>
+bool FactoryLoader<T>::findFactoryForScheme(
+ int32_t CA_system_id, sp<SharedLibrary> *library, T** factory) {
+ if (library != NULL) {
+ library->clear();
+ }
+ if (factory != NULL) {
+ *factory = NULL;
+ }
+
+ Mutex::Autolock autoLock(mMapLock);
+
+ // first check cache
+ ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
+ if (index >= 0) {
+ return loadFactoryForSchemeFromPath(
+ mCASystemIdToLibraryPathMap[index],
+ CA_system_id, library, factory);
+ }
+
+ // no luck, have to search
+ String8 dirPath("/vendor/lib/mediacas");
+ DIR* pDir = opendir(dirPath.string());
+
+ if (pDir == NULL) {
+ ALOGE("Failed to open plugin directory %s", dirPath.string());
+ return false;
+ }
+
+ struct dirent* pEntry;
+ while ((pEntry = readdir(pDir))) {
+ String8 pluginPath = dirPath + "/" + pEntry->d_name;
+ if (pluginPath.getPathExtension() == ".so") {
+ if (loadFactoryForSchemeFromPath(
+ pluginPath, CA_system_id, library, factory)) {
+ mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
+ closedir(pDir);
+
+ return true;
+ }
+ }
+ }
+
+ closedir(pDir);
+
+ ALOGE("Failed to find plugin");
+ return false;
+}
+
+template <class T>
+bool FactoryLoader<T>::enumeratePlugins(
+ vector<HidlCasPluginDescriptor>* results) {
+ ALOGI("enumeratePlugins");
+
+ results->clear();
+
+ String8 dirPath("/vendor/lib/mediacas");
+ DIR* pDir = opendir(dirPath.string());
+
+ if (pDir == NULL) {
+ ALOGE("Failed to open plugin directory %s", dirPath.string());
+ return false;
+ }
+
+ Mutex::Autolock autoLock(mMapLock);
+
+ struct dirent* pEntry;
+ while ((pEntry = readdir(pDir))) {
+ String8 pluginPath = dirPath + "/" + pEntry->d_name;
+ if (pluginPath.getPathExtension() == ".so") {
+ queryPluginsFromPath(pluginPath, results);
+ }
+ }
+ return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::loadFactoryForSchemeFromPath(
+ const String8 &path, int32_t CA_system_id,
+ sp<SharedLibrary> *library, T** factory) {
+ closeFactory();
+
+ if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
+ closeFactory();
+ return false;
+ }
+
+ if (library != NULL) {
+ *library = mLibrary;
+ }
+ if (factory != NULL) {
+ *factory = mFactory;
+ }
+ return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::queryPluginsFromPath(
+ const String8 &path, vector<HidlCasPluginDescriptor>* results) {
+ closeFactory();
+
+ vector<CasPluginDescriptor> descriptors;
+ if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
+ closeFactory();
+ return false;
+ }
+
+ for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
+ results->push_back( HidlCasPluginDescriptor {
+ .caSystemId = it->CA_system_id,
+ .name = it->name.c_str()});
+ }
+ return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::openFactory(const String8 &path) {
+ // get strong pointer to open shared library
+ ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
+ if (index >= 0) {
+ mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
+ } else {
+ index = mLibraryPathToOpenLibraryMap.add(path, NULL);
+ }
+
+ if (!mLibrary.get()) {
+ mLibrary = new SharedLibrary(path);
+ if (!*mLibrary) {
+ return false;
+ }
+
+ mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
+ }
+
+ CreateFactoryFunc createFactory =
+ (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
+ if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
+ return false;
+ }
+ return true;
+}
+
+template <class T>
+void FactoryLoader<T>::closeFactory() {
+ delete mFactory;
+ mFactory = NULL;
+ mLibrary.clear();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
diff --git a/cas/1.0/default/MediaCasService.cpp b/cas/1.0/default/MediaCasService.cpp
new file mode 100644
index 0000000..ca43224
--- /dev/null
+++ b/cas/1.0/default/MediaCasService.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-MediaCasService"
+
+#include <android/hardware/cas/1.0/ICasListener.h>
+#include <media/cas/CasAPI.h>
+#include <media/cas/DescramblerAPI.h>
+#include <utils/Log.h>
+
+#include "CasImpl.h"
+#include "DescramblerImpl.h"
+#include "MediaCasService.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+MediaCasService::MediaCasService() :
+ mCasLoader("createCasFactory"),
+ mDescramblerLoader("createDescramblerFactory") {
+}
+
+MediaCasService::~MediaCasService() {
+}
+
+Return<void> MediaCasService::enumeratePlugins(enumeratePlugins_cb _hidl_cb) {
+
+ ALOGV("%s", __FUNCTION__);
+
+ vector<HidlCasPluginDescriptor> results;
+ mCasLoader.enumeratePlugins(&results);
+
+ _hidl_cb(results);
+ return Void();
+}
+
+Return<bool> MediaCasService::isSystemIdSupported(int32_t CA_system_id) {
+ ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id);
+
+ return mCasLoader.findFactoryForScheme(CA_system_id);
+}
+
+Return<sp<ICas>> MediaCasService::createPlugin(
+ int32_t CA_system_id, const sp<ICasListener>& listener) {
+
+ ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+ sp<ICas> result;
+
+ CasFactory *factory;
+ sp<SharedLibrary> library;
+ if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) {
+ CasPlugin *plugin = NULL;
+ sp<CasImpl> casImpl = new CasImpl(listener);
+ if (factory->createPlugin(CA_system_id, (uint64_t)casImpl.get(),
+ &CasImpl::OnEvent, &plugin) == OK && plugin != NULL) {
+ casImpl->init(library, plugin);
+ result = casImpl;
+ }
+ }
+
+ return result;
+}
+
+Return<bool> MediaCasService::isDescramblerSupported(int32_t CA_system_id) {
+ ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+ return mDescramblerLoader.findFactoryForScheme(CA_system_id);
+}
+
+Return<sp<IDescramblerBase>> MediaCasService::createDescrambler(int32_t CA_system_id) {
+
+ ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+ sp<IDescrambler> result;
+
+ DescramblerFactory *factory;
+ sp<SharedLibrary> library;
+ if (mDescramblerLoader.findFactoryForScheme(
+ CA_system_id, &library, &factory)) {
+ DescramblerPlugin *plugin = NULL;
+ if (factory->createPlugin(CA_system_id, &plugin) == OK
+ && plugin != NULL) {
+ result = new DescramblerImpl(library, plugin);
+ }
+ }
+
+ return result;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/MediaCasService.h b/cas/1.0/default/MediaCasService.h
new file mode 100644
index 0000000..77ddac6
--- /dev/null
+++ b/cas/1.0/default/MediaCasService.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_MEDIA_CAS_SERVICE_H_
+#define ANDROID_HARDWARE_CAS_V1_0_MEDIA_CAS_SERVICE_H_
+
+#include <android/hardware/cas/1.0/IMediaCasService.h>
+
+#include "FactoryLoader.h"
+
+namespace android {
+struct CasFactory;
+struct DescramblerFactory;
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+class MediaCasService : public IMediaCasService {
+public:
+ MediaCasService();
+
+ virtual Return<void> enumeratePlugins(
+ enumeratePlugins_cb _hidl_cb) override;
+
+ virtual Return<bool> isSystemIdSupported(
+ int32_t CA_system_id) override;
+
+ virtual Return<sp<ICas>> createPlugin(
+ int32_t CA_system_id, const sp<ICasListener>& listener) override;
+
+ virtual Return<bool> isDescramblerSupported(
+ int32_t CA_system_id) override;
+
+ virtual Return<sp<IDescramblerBase>> createDescrambler(
+ int32_t CA_system_id) override;
+
+private:
+ FactoryLoader<CasFactory> mCasLoader;
+ FactoryLoader<DescramblerFactory> mDescramblerLoader;
+
+ virtual ~MediaCasService();
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_MEDIA_CAS_SERVICE_H_
diff --git a/cas/1.0/default/SharedLibrary.cpp b/cas/1.0/default/SharedLibrary.cpp
new file mode 100644
index 0000000..9c7f385
--- /dev/null
+++ b/cas/1.0/default/SharedLibrary.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-SharedLibrary"
+
+#include <dlfcn.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include "SharedLibrary.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+SharedLibrary::SharedLibrary(const String8 &path) {
+ mLibHandle = dlopen(path.string(), RTLD_NOW);
+}
+
+SharedLibrary::~SharedLibrary() {
+ if (mLibHandle != NULL) {
+ dlclose(mLibHandle);
+ mLibHandle = NULL;
+ }
+}
+
+bool SharedLibrary::operator!() const {
+ return mLibHandle == NULL;
+}
+
+void *SharedLibrary::lookup(const char *symbol) const {
+ if (!mLibHandle) {
+ return NULL;
+ }
+ // Clear last error before we load the symbol again,
+ // in case the caller didn't retrieve it.
+ (void)dlerror();
+ return dlsym(mLibHandle, symbol);
+}
+
+const char *SharedLibrary::lastError() const {
+ const char *error = dlerror();
+ return error ? error : "No errors or unknown error";
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/SharedLibrary.h b/cas/1.0/default/SharedLibrary.h
new file mode 100644
index 0000000..18130a5
--- /dev/null
+++ b/cas/1.0/default/SharedLibrary.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
+#define ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+class SharedLibrary : public RefBase {
+public:
+ explicit SharedLibrary(const String8 &path);
+ ~SharedLibrary();
+
+ bool operator!() const;
+ void *lookup(const char *symbol) const;
+ const char *lastError() const;
+
+private:
+ void *mLibHandle;
+ DISALLOW_EVIL_CONSTRUCTORS(SharedLibrary);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
diff --git a/cas/1.0/default/TypeConvert.cpp b/cas/1.0/default/TypeConvert.cpp
new file mode 100644
index 0000000..de1f92b
--- /dev/null
+++ b/cas/1.0/default/TypeConvert.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-TypeConvert"
+
+#include <utils/Log.h>
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus) {
+ Status status;
+ switch(legacyStatus) {
+ case android::OK:
+ status = Status::OK;
+ break;
+ case android::ERROR_CAS_NO_LICENSE:
+ status = Status::ERROR_CAS_NO_LICENSE;
+ break;
+ case android::ERROR_CAS_LICENSE_EXPIRED:
+ status = Status::ERROR_CAS_LICENSE_EXPIRED;
+ break;
+ case android::ERROR_CAS_SESSION_NOT_OPENED:
+ status = Status::ERROR_CAS_SESSION_NOT_OPENED;
+ break;
+ case android::ERROR_CAS_CANNOT_HANDLE:
+ status = Status::ERROR_CAS_CANNOT_HANDLE;
+ break;
+ case android::ERROR_CAS_TAMPER_DETECTED:
+ status = Status::ERROR_CAS_INVALID_STATE;
+ break;
+ case android::BAD_VALUE:
+ status = Status::BAD_VALUE;
+ break;
+ case android::ERROR_CAS_NOT_PROVISIONED:
+ status = Status::ERROR_CAS_NOT_PROVISIONED;
+ break;
+ case android::ERROR_CAS_RESOURCE_BUSY:
+ status = Status::ERROR_CAS_RESOURCE_BUSY;
+ break;
+ case android::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION:
+ status = Status::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION;
+ break;
+ case android::ERROR_CAS_DEVICE_REVOKED:
+ status = Status::ERROR_CAS_DEVICE_REVOKED;
+ break;
+ case android::ERROR_CAS_DECRYPT:
+ status = Status::ERROR_CAS_DECRYPT;
+ break;
+ default:
+ ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN",
+ legacyStatus);
+ status = Status::ERROR_CAS_UNKNOWN;
+ break;
+ }
+ return status;
+}
+
+String8 sessionIdToString(const CasSessionId &sessionId) {
+ String8 result;
+ for (size_t i = 0; i < sessionId.size(); i++) {
+ result.appendFormat("%02x ", sessionId[i]);
+ }
+ if (result.isEmpty()) {
+ result.append("(null)");
+ }
+ return result;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/TypeConvert.h b/cas/1.0/default/TypeConvert.h
new file mode 100644
index 0000000..7c3dded
--- /dev/null
+++ b/cas/1.0/default/TypeConvert.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_TYPE_CONVERT_H
+#define ANDROID_HARDWARE_CAS_V1_0_TYPE_CONVERT_H
+
+#include <android/hardware/cas/1.0/types.h>
+#include <media/cas/CasAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus);
+
+String8 sessionIdToString(const CasSessionId &sessionId);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_TYPE_CONVERT_H
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service.rc b/cas/1.0/default/android.hardware.cas@1.0-service.rc
new file mode 100644
index 0000000..93de794
--- /dev/null
+++ b/cas/1.0/default/android.hardware.cas@1.0-service.rc
@@ -0,0 +1,6 @@
+service cas-hal-1-0 /vendor/bin/hw/android.hardware.cas@1.0-service
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ writepid /dev/cpuset/foreground/tasks
diff --git a/cas/1.0/default/service.cpp b/cas/1.0/default/service.cpp
new file mode 100644
index 0000000..3f1df5a
--- /dev/null
+++ b/cas/1.0/default/service.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-service"
+
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+#include "MediaCasService.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::cas::V1_0::implementation::MediaCasService;
+using android::hardware::cas::V1_0::IMediaCasService;
+
+int main() {
+ ALOGD("android.hardware.cas@1.0-service starting...");
+
+#ifdef USE_VNDBINDER
+ // The CAS HAL may communicate to other vendor components via
+ // /dev/vndbinder
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+#endif // USE_VNDBINDER
+
+ configureRpcThreadpool(8, true /* callerWillJoin */);
+
+ // Setup hwbinder service
+ android::sp<IMediaCasService> service = new MediaCasService();
+ android::status_t status = service->registerAsService();
+ LOG_ALWAYS_FATAL_IF(
+ status != android::OK,
+ "Error while registering cas service: %d", status);
+ joinRpcThreadpool();
+ return 0;
+}
diff --git a/cas/1.0/types.hal b/cas/1.0/types.hal
new file mode 100644
index 0000000..7337f00
--- /dev/null
+++ b/cas/1.0/types.hal
@@ -0,0 +1,124 @@
+/**
+ * Copyright (C) 2017 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.cas@1.0;
+
+enum Status : uint32_t {
+ /**
+ * The CAS plugin must return OK when an operation completes without any
+ * errors.
+ */
+ OK,
+
+ /**
+ * The CAS plugin must return ERROR_CAS_NO_LICENSE, when descrambling is
+ * attempted and no license keys have been provided.
+ */
+ ERROR_CAS_NO_LICENSE,
+
+ /**
+ * ERROR_CAS_LICENSE_EXPIRED must be returned when an attempt is made
+ * to use a license and the keys in that license have expired.
+ */
+ ERROR_CAS_LICENSE_EXPIRED,
+
+ /**
+ * The CAS plugin must return ERROR_CAS_SESSION_NOT_OPENED when an
+ * attempt is made to use a session that has not been opened.
+ */
+ ERROR_CAS_SESSION_NOT_OPENED,
+
+ /**
+ * The CAS plugin must return ERROR_CAS_CANNOT_HANDLE when an unsupported
+ * data format or operation is attempted.
+ */
+ ERROR_CAS_CANNOT_HANDLE,
+
+ /**
+ * ERROR_CAS_INVALID_STATE must be returned when the device is in a state
+ * where it is not able to perform descrambling.
+ */
+ ERROR_CAS_INVALID_STATE,
+
+ /**
+ * The CAS plugin must return BAD_VALUE whenever an illegal parameter is
+ * passed to one of the interface functions.
+ */
+ BAD_VALUE,
+
+ /**
+ * The CAS plugin must return ERROR_CAS_NOT_PROVISIONED when the device
+ * has not yet been provisioned.
+ */
+ ERROR_CAS_NOT_PROVISIONED,
+
+ /**
+ * ERROR_CAS_RESOURCE_BUSY must be returned when resources, such as CAS
+ * sessions or secure buffers are not available to perform a requested
+ * operation because they are already in use.
+ */
+ ERROR_CAS_RESOURCE_BUSY,
+
+ /**
+ * The CAS Plugin must return ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION
+ * when the output protection level enabled on the device is not
+ * sufficient to meet the requirements in the license policy. HDCP is an
+ * example of a form of output protection.
+ */
+ ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION,
+
+ /**
+ * The CAS Plugin must return ERROR_CAS_TAMPER_DETECTED if an attempt to
+ * tamper with the CAS system is detected.
+ */
+ ERROR_CAS_TAMPER_DETECTED,
+
+ /**
+ * The CAS Plugin must return ERROR_CAS_DEVICE_REVOKED if the response
+ * indicates that the device has been revoked. Device revocation means
+ * that the device is no longer permitted to play content.
+ */
+ ERROR_CAS_DEVICE_REVOKED,
+
+ /**
+ * The CAS plugin must return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED when
+ * descrambling is failing because the session is not initialized properly.
+ */
+ ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED,
+
+ /**
+ * The CAS Plugin must return ERROR_CAS_DECRYPT if the DescramblerPlugin's
+ * descramble operation fails.
+ */
+ ERROR_CAS_DECRYPT,
+
+ /**
+ * ERROR_CAS_UNKNOWN must be returned when a fatal failure occurs and no
+ * other defined error is appropriate.
+ */
+ ERROR_CAS_UNKNOWN,
+};
+
+typedef vec<uint8_t> HidlCasSessionId;
+typedef vec<uint8_t> HidlCasData;
+
+/**
+ * Describes a CAS plugin with its system id and name.
+ */
+struct HidlCasPluginDescriptor {
+ int32_t caSystemId;
+ string name;
+};