mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge changes from topic "cas_aidl" am: 9d7488c540 am: bf30bc6187
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2222080 Change-Id: I75bb3cd810f3bf7be1f52800b9e29d2439ed409c Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
31
cas/aidl/Android.bp
Normal file
31
cas/aidl/Android.bp
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
aidl_interface {
|
||||
name: "android.hardware.cas",
|
||||
vendor_available: true,
|
||||
srcs: ["android/hardware/cas/*.aidl"],
|
||||
stability: "vintf",
|
||||
imports: ["android.hardware.common-V2"],
|
||||
backend: {
|
||||
cpp: {
|
||||
enabled: false,
|
||||
},
|
||||
java: {
|
||||
sdk_version: "module_current",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
parcelable AidlCasPluginDescriptor {
|
||||
int caSystemId;
|
||||
String name;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
union DestinationBuffer {
|
||||
android.hardware.cas.SharedBuffer nonsecureMemory;
|
||||
android.hardware.common.NativeHandle secureMemory;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
interface ICas {
|
||||
void closeSession(in byte[] sessionId);
|
||||
byte[] openSession(in android.hardware.cas.SessionIntent intent, in android.hardware.cas.ScramblingMode mode);
|
||||
void processEcm(in byte[] sessionId, in byte[] ecm);
|
||||
void processEmm(in byte[] emm);
|
||||
void provision(in String provisionString);
|
||||
void refreshEntitlements(in int refreshType, in byte[] refreshData);
|
||||
void release();
|
||||
void sendEvent(in int event, in int arg, in byte[] eventData);
|
||||
void sendSessionEvent(in byte[] sessionId, in int event, in int arg, in byte[] eventData);
|
||||
void setPrivateData(in byte[] pvtData);
|
||||
void setSessionPrivateData(in byte[] sessionId, in byte[] pvtData);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
interface ICasListener {
|
||||
void onEvent(in int event, in int arg, in byte[] data);
|
||||
void onSessionEvent(in byte[] sessionId, in int event, in int arg, in byte[] data);
|
||||
void onStatusUpdate(in android.hardware.cas.StatusEvent event, in int number);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
interface IDescrambler {
|
||||
int descramble(in android.hardware.cas.ScramblingControl scramblingControl, in android.hardware.cas.SubSample[] subSamples, in android.hardware.cas.SharedBuffer srcBuffer, in long srcOffset, in android.hardware.cas.DestinationBuffer dstBuffer, in long dstOffset);
|
||||
void release();
|
||||
boolean requiresSecureDecoderComponent(in String mime);
|
||||
void setMediaCasSession(in byte[] sessionId);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
interface IMediaCasService {
|
||||
android.hardware.cas.IDescrambler createDescrambler(in int CA_system_id);
|
||||
android.hardware.cas.ICas createPlugin(in int CA_system_id, in android.hardware.cas.ICasListener listener);
|
||||
android.hardware.cas.AidlCasPluginDescriptor[] enumeratePlugins();
|
||||
boolean isDescramblerSupported(in int CA_system_id);
|
||||
boolean isSystemIdSupported(in int CA_system_id);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum ScramblingControl {
|
||||
UNSCRAMBLED = 0,
|
||||
RESERVED = 1,
|
||||
EVENKEY = 2,
|
||||
ODDKEY = 3,
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum ScramblingMode {
|
||||
RESERVED = 0,
|
||||
DVB_CSA1 = 1,
|
||||
DVB_CSA2 = 2,
|
||||
DVB_CSA3_STANDARD = 3,
|
||||
DVB_CSA3_MINIMAL = 4,
|
||||
DVB_CSA3_ENHANCE = 5,
|
||||
DVB_CISSA_V1 = 6,
|
||||
DVB_IDSA = 7,
|
||||
MULTI2 = 8,
|
||||
AES128 = 9,
|
||||
AES_CBC = 10,
|
||||
AES_ECB = 11,
|
||||
AES_SCTE52 = 12,
|
||||
TDES_ECB = 13,
|
||||
TDES_SCTE52 = 14,
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum SessionIntent {
|
||||
LIVE = 0,
|
||||
PLAYBACK = 1,
|
||||
RECORD = 2,
|
||||
TIMESHIFT = 3,
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
parcelable SharedBuffer {
|
||||
android.hardware.common.Ashmem heapBase;
|
||||
long offset;
|
||||
long size;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
parcelable Status {
|
||||
const int OK = 0;
|
||||
const int ERROR_CAS_NO_LICENSE = -1;
|
||||
const int ERROR_CAS_LICENSE_EXPIRED = -2;
|
||||
const int ERROR_CAS_SESSION_NOT_OPENED = -3;
|
||||
const int ERROR_CAS_CANNOT_HANDLE = -4;
|
||||
const int ERROR_CAS_INVALID_STATE = -5;
|
||||
const int BAD_VALUE = -6;
|
||||
const int ERROR_CAS_NOT_PROVISIONED = -7;
|
||||
const int ERROR_CAS_RESOURCE_BUSY = -8;
|
||||
const int ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = -9;
|
||||
const int ERROR_CAS_TAMPER_DETECTED = -10;
|
||||
const int ERROR_CAS_DEVICE_REVOKED = -11;
|
||||
const int ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = -12;
|
||||
const int ERROR_CAS_DECRYPT = -13;
|
||||
const int ERROR_CAS_UNKNOWN = -14;
|
||||
const int ERROR_CAS_NEED_ACTIVATION = -15;
|
||||
const int ERROR_CAS_NEED_PAIRING = -16;
|
||||
const int ERROR_CAS_NO_CARD = -17;
|
||||
const int ERROR_CAS_CARD_MUTE = -18;
|
||||
const int ERROR_CAS_CARD_INVALID = -19;
|
||||
const int ERROR_CAS_BLACKOUT = -20;
|
||||
const int ERROR_CAS_REBOOTING = -21;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@Backing(type="byte") @VintfStability
|
||||
enum StatusEvent {
|
||||
PLUGIN_PHYSICAL_MODULE_CHANGED = 0,
|
||||
PLUGIN_SESSION_NUMBER_CHANGED = 1,
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file 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.cas;
|
||||
@VintfStability
|
||||
parcelable SubSample {
|
||||
int numBytesOfClearData;
|
||||
int numBytesOfEncryptedData;
|
||||
}
|
||||
26
cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
Normal file
26
cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
/**
|
||||
* Describes a CAS plugin with its system ID and name.
|
||||
*/
|
||||
@VintfStability
|
||||
parcelable AidlCasPluginDescriptor {
|
||||
int caSystemId;
|
||||
String name;
|
||||
}
|
||||
35
cas/aidl/android/hardware/cas/DestinationBuffer.aidl
Normal file
35
cas/aidl/android/hardware/cas/DestinationBuffer.aidl
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import android.hardware.cas.SharedBuffer;
|
||||
import android.hardware.common.NativeHandle;
|
||||
|
||||
@VintfStability
|
||||
union DestinationBuffer {
|
||||
/**
|
||||
* If type == SHARED_MEMORY, the descrambled data must be written
|
||||
* to user-space non-secure shared memory.
|
||||
*/
|
||||
SharedBuffer nonsecureMemory;
|
||||
|
||||
/**
|
||||
* If type == NATIVE_HANDLE, the descrambled data must be written
|
||||
* to secure memory referenced by the vendor's buffer allocator.
|
||||
*/
|
||||
NativeHandle secureMemory;
|
||||
}
|
||||
121
cas/aidl/android/hardware/cas/ICas.aidl
Normal file
121
cas/aidl/android/hardware/cas/ICas.aidl
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import android.hardware.cas.ScramblingMode;
|
||||
import android.hardware.cas.SessionIntent;
|
||||
|
||||
/**
|
||||
* ICas is the API to control the CAS. 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.
|
||||
*/
|
||||
@VintfStability
|
||||
interface ICas {
|
||||
/**
|
||||
* Close a session.
|
||||
*
|
||||
* @param sessionId The id of the session to be closed.
|
||||
*/
|
||||
void closeSession(in byte[] sessionId);
|
||||
|
||||
/**
|
||||
* Open a session to descramble one or more streams by specifying intention
|
||||
* and scrambling mode.
|
||||
*
|
||||
* @param intent the intention of the session to be opened.
|
||||
* @param mode the scrambling mode the session will use.
|
||||
*
|
||||
* @return sessionId The id of the newly opened session.
|
||||
*/
|
||||
byte[] openSession(in SessionIntent intent, in ScramblingMode mode);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void processEcm(in byte[] sessionId, in byte[] ecm);
|
||||
|
||||
/**
|
||||
* Process an in-band EMM from the EMM stream.
|
||||
*
|
||||
* @param emm a byte array containing the emm data.
|
||||
*/
|
||||
void processEmm(in byte[] emm);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void provision(in String provisionString);
|
||||
|
||||
/**
|
||||
* Notify the CA system to refresh entitlement keys.
|
||||
*
|
||||
* @param refreshType the type of the refreshment.
|
||||
* @param refreshData private data associated with the refreshment.
|
||||
*/
|
||||
void refreshEntitlements(in int refreshType, in byte[] refreshData);
|
||||
|
||||
/**
|
||||
* Release the descrambler instance.
|
||||
*/
|
||||
void release();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void sendEvent(in int event, in int arg, in byte[] eventData);
|
||||
|
||||
/**
|
||||
* Send an scheme-specific session event to the CasPlugin.
|
||||
*
|
||||
* @param sessionId the id of an opened session.
|
||||
* @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.
|
||||
*/
|
||||
void sendSessionEvent(in byte[] sessionId, in int event, in int arg, in byte[] eventData);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void setPrivateData(in byte[] pvtData);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void setSessionPrivateData(in byte[] sessionId, in byte[] pvtData);
|
||||
}
|
||||
58
cas/aidl/android/hardware/cas/ICasListener.aidl
Normal file
58
cas/aidl/android/hardware/cas/ICasListener.aidl
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import android.hardware.cas.StatusEvent;
|
||||
|
||||
@VintfStability
|
||||
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.
|
||||
*/
|
||||
void onEvent(in int event, in int arg, in byte[] data);
|
||||
|
||||
/**
|
||||
* Notify the listener of a scheme-specific session event from CA system.
|
||||
*
|
||||
* @param sessionId the id of an opened session.
|
||||
* @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.
|
||||
*/
|
||||
void onSessionEvent(in byte[] sessionId, in int event, in int arg, in byte[] data);
|
||||
|
||||
/**
|
||||
* Notify the listener that the status of CAS system has changed.
|
||||
*
|
||||
* @param event the event type of status change.
|
||||
* @param number value for status event.
|
||||
* For PLUGIN_PHYSICAL_MODULE_CHANGED event:
|
||||
* the positive number presents how many plugins are inserted;
|
||||
* the negative number presents how many plugins are removed.
|
||||
* Client must enumerate plugins after receive the event.
|
||||
* For PLUGIN_SESSION_NUMBER_CHANGED event:
|
||||
* the number presents how many sessions are supported
|
||||
* in the plugin.
|
||||
*/
|
||||
void onStatusUpdate(in StatusEvent event, in int number);
|
||||
}
|
||||
68
cas/aidl/android/hardware/cas/IDescrambler.aidl
Normal file
68
cas/aidl/android/hardware/cas/IDescrambler.aidl
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import android.hardware.cas.DestinationBuffer;
|
||||
import android.hardware.cas.ScramblingControl;
|
||||
import android.hardware.cas.SharedBuffer;
|
||||
import android.hardware.cas.SubSample;
|
||||
|
||||
/**
|
||||
* IDescrambler is the API to control the descrambling operations.
|
||||
*/
|
||||
@VintfStability
|
||||
interface IDescrambler {
|
||||
/**
|
||||
* Descramble the data in a source SharedBuffer, described by an array of
|
||||
* SubSample structures.
|
||||
*
|
||||
* @param scramblingControl an enumeration indicating the key that the subsamples
|
||||
* were scrambled with.
|
||||
* @param subSamples an array of SubSample structures describing the number of
|
||||
* clear and scrambled bytes within each subsample.
|
||||
* @param srcBuffer the SharedBuffer containing the source scrambled data.
|
||||
* @param srcOffset the position where the source scrambled data starts at.
|
||||
* @param dstBuffer the DestinationBuffer to hold the descrambled data.
|
||||
* @param dstOffset the position where the descrambled data should start at.
|
||||
*
|
||||
* @return bytesWritten Number of bytes that have been successfully written.
|
||||
*/
|
||||
int descramble(in ScramblingControl scramblingControl, in SubSample[] subSamples,
|
||||
in SharedBuffer srcBuffer, in long srcOffset, in DestinationBuffer dstBuffer,
|
||||
in long dstOffset);
|
||||
|
||||
/**
|
||||
* Release the descrambler instance.
|
||||
*/
|
||||
void release();
|
||||
|
||||
/**
|
||||
* 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 whether the descrambler requires a secure decoder.
|
||||
*/
|
||||
boolean requiresSecureDecoderComponent(in String mime);
|
||||
|
||||
/**
|
||||
* Associate a MediaCas session with this MediaDescrambler instance.
|
||||
*
|
||||
* @param sessionId the id of the session to associate with this descrambler instance.
|
||||
*/
|
||||
void setMediaCasSession(in byte[] sessionId);
|
||||
}
|
||||
71
cas/aidl/android/hardware/cas/IMediaCasService.aidl
Normal file
71
cas/aidl/android/hardware/cas/IMediaCasService.aidl
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import android.hardware.cas.AidlCasPluginDescriptor;
|
||||
import android.hardware.cas.ICas;
|
||||
import android.hardware.cas.ICasListener;
|
||||
import android.hardware.cas.IDescrambler;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@VintfStability
|
||||
interface IMediaCasService {
|
||||
/**
|
||||
* Construct a new instance of a DescramblerPlugin given a CA_system_id.
|
||||
*
|
||||
* @param CA_system_id the id of the CA system.
|
||||
* @return the newly created plugin interface.
|
||||
*/
|
||||
IDescrambler createDescrambler(in int CA_system_id);
|
||||
|
||||
/**
|
||||
* 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 the newly created CasPlugin interface.
|
||||
*/
|
||||
ICas createPlugin(in int CA_system_id, in ICasListener listener);
|
||||
|
||||
/**
|
||||
* List all available CA systems on the device.
|
||||
*
|
||||
* @return an array of descriptors for the available CA systems.
|
||||
*/
|
||||
AidlCasPluginDescriptor[] enumeratePlugins();
|
||||
|
||||
/**
|
||||
* 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 whether the specified descrambling scheme is supported on this device.
|
||||
*/
|
||||
boolean isDescramblerSupported(in int CA_system_id);
|
||||
|
||||
/**
|
||||
* Query if a certain CA system is supported on this device.
|
||||
*
|
||||
* @param CA_system_id the id of the CA system.
|
||||
* @return whether the specified CA system is supported on this device.
|
||||
*/
|
||||
boolean isSystemIdSupported(in int CA_system_id);
|
||||
}
|
||||
29
cas/aidl/android/hardware/cas/ScramblingControl.aidl
Normal file
29
cas/aidl/android/hardware/cas/ScramblingControl.aidl
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
/**
|
||||
* Enumerates the keys used to scramble the content.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type="int")
|
||||
enum ScramblingControl {
|
||||
UNSCRAMBLED = 0,
|
||||
RESERVED = 1,
|
||||
EVENKEY = 2,
|
||||
ODDKEY = 3,
|
||||
}
|
||||
98
cas/aidl/android/hardware/cas/ScramblingMode.aidl
Normal file
98
cas/aidl/android/hardware/cas/ScramblingMode.aidl
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
/**
|
||||
* The Scrambling Mode.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type="int")
|
||||
enum ScramblingMode {
|
||||
RESERVED = 0,
|
||||
|
||||
/**
|
||||
* DVB (Digital Video Broadcasting) CSA1 (Common Scrambling Algorithm 1) is
|
||||
* the default mode and shall be used when the scrambling descriptor
|
||||
* is not present in the program map section. DVB scrambling mode is
|
||||
* specified in ETSI EN 300 468 specification.
|
||||
*/
|
||||
DVB_CSA1,
|
||||
|
||||
DVB_CSA2,
|
||||
|
||||
/**
|
||||
* DVB-CSA3 in standard mode.
|
||||
*/
|
||||
DVB_CSA3_STANDARD,
|
||||
|
||||
/**
|
||||
* DVB-CSA3 in minimally enhanced mode.
|
||||
*/
|
||||
DVB_CSA3_MINIMAL,
|
||||
|
||||
/**
|
||||
* DVB-CSA3 in fully enhanced mode.
|
||||
*/
|
||||
DVB_CSA3_ENHANCE,
|
||||
|
||||
/**
|
||||
* DVB-CISSA version 1.
|
||||
*/
|
||||
DVB_CISSA_V1,
|
||||
|
||||
/**
|
||||
* ATIS-0800006 IIF Default Scrambling Algorithm (IDSA).
|
||||
*/
|
||||
DVB_IDSA,
|
||||
|
||||
/**
|
||||
* a symmetric key algorithm.
|
||||
*/
|
||||
MULTI2,
|
||||
|
||||
/**
|
||||
* Advanced Encryption System (AES) 128-bit Encryption mode.
|
||||
*/
|
||||
AES128,
|
||||
|
||||
/**
|
||||
* Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode.
|
||||
*/
|
||||
AES_CBC,
|
||||
|
||||
/**
|
||||
* Advanced Encryption System (AES) Electronic Code Book (ECB) mode.
|
||||
*/
|
||||
AES_ECB,
|
||||
|
||||
/**
|
||||
* Advanced Encryption System (AES) Society of Cable Telecommunications
|
||||
* Engineers (SCTE) 52 mode.
|
||||
*/
|
||||
AES_SCTE52,
|
||||
|
||||
/**
|
||||
* Triple Data Encryption Algorithm (TDES) Electronic Code Book (ECB) mode.
|
||||
*/
|
||||
TDES_ECB,
|
||||
|
||||
/**
|
||||
* Triple Data Encryption Algorithm (TDES) Society of Cable Telecommunications
|
||||
* Engineers (SCTE) 52 mode.
|
||||
*/
|
||||
TDES_SCTE52,
|
||||
}
|
||||
44
cas/aidl/android/hardware/cas/SessionIntent.aidl
Normal file
44
cas/aidl/android/hardware/cas/SessionIntent.aidl
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
/**
|
||||
* The intented usage for the session.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type="int")
|
||||
enum SessionIntent {
|
||||
/**
|
||||
* Live Stream.
|
||||
*/
|
||||
LIVE,
|
||||
|
||||
/**
|
||||
* Playback Recorded Stream.
|
||||
*/
|
||||
PLAYBACK,
|
||||
|
||||
/**
|
||||
* Record Live Stream.
|
||||
*/
|
||||
RECORD,
|
||||
|
||||
/**
|
||||
* View the content with Time Shift capability
|
||||
*/
|
||||
TIMESHIFT,
|
||||
}
|
||||
42
cas/aidl/android/hardware/cas/SharedBuffer.aidl
Normal file
42
cas/aidl/android/hardware/cas/SharedBuffer.aidl
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import android.hardware.common.Ashmem;
|
||||
|
||||
/**
|
||||
* SharedBuffer describes a shared buffer which is defined by a heapBase, an
|
||||
* offset and a size. The offset is relative to the shared memory base for the
|
||||
* memory region identified by heapBase.
|
||||
*/
|
||||
@VintfStability
|
||||
parcelable SharedBuffer {
|
||||
/**
|
||||
* Ashmem shared memory
|
||||
*/
|
||||
Ashmem heapBase;
|
||||
|
||||
/**
|
||||
* The offset from the shared memory base
|
||||
*/
|
||||
long offset;
|
||||
|
||||
/**
|
||||
* The size of the shared buffer in bytes
|
||||
*/
|
||||
long size;
|
||||
}
|
||||
150
cas/aidl/android/hardware/cas/Status.aidl
Normal file
150
cas/aidl/android/hardware/cas/Status.aidl
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
@VintfStability
|
||||
parcelable Status {
|
||||
/**
|
||||
* The CAS plugin must return OK when an operation completes without any
|
||||
* errors.
|
||||
*/
|
||||
const int OK = 0;
|
||||
|
||||
/**
|
||||
* The CAS plugin must return ERROR_CAS_NO_LICENSE, when descrambling is
|
||||
* attempted and no license keys have been provided.
|
||||
*/
|
||||
const int ERROR_CAS_NO_LICENSE = -1;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_LICENSE_EXPIRED must be returned when an attempt is made
|
||||
* to use a license and the keys in that license have expired.
|
||||
*/
|
||||
const int ERROR_CAS_LICENSE_EXPIRED = -2;
|
||||
|
||||
/**
|
||||
* The CAS plugin must return ERROR_CAS_SESSION_NOT_OPENED when an
|
||||
* attempt is made to use a session that has not been opened.
|
||||
*/
|
||||
const int ERROR_CAS_SESSION_NOT_OPENED = -3;
|
||||
|
||||
/**
|
||||
* The CAS plugin must return ERROR_CAS_CANNOT_HANDLE when an unsupported
|
||||
* data format or operation is attempted.
|
||||
*/
|
||||
const int ERROR_CAS_CANNOT_HANDLE = -4;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_INVALID_STATE must be returned when the device is in a state
|
||||
* where it is not able to perform descrambling.
|
||||
*/
|
||||
const int ERROR_CAS_INVALID_STATE = -5;
|
||||
|
||||
/**
|
||||
* The CAS plugin must return BAD_VALUE whenever an illegal parameter is
|
||||
* passed to one of the interface functions.
|
||||
*/
|
||||
const int BAD_VALUE = -6;
|
||||
|
||||
/**
|
||||
* The CAS plugin must return ERROR_CAS_NOT_PROVISIONED when the device
|
||||
* has not yet been provisioned.
|
||||
*/
|
||||
const int ERROR_CAS_NOT_PROVISIONED = -7;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
const int ERROR_CAS_RESOURCE_BUSY = -8;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
const int ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = -9;
|
||||
|
||||
/**
|
||||
* The CAS Plugin must return ERROR_CAS_TAMPER_DETECTED if an attempt to
|
||||
* tamper with the CAS system is detected.
|
||||
*/
|
||||
const int ERROR_CAS_TAMPER_DETECTED = -10;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
const int ERROR_CAS_DEVICE_REVOKED = -11;
|
||||
|
||||
/**
|
||||
* The CAS plugin must return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED when
|
||||
* descrambling is failing because the session is not initialized properly.
|
||||
*/
|
||||
const int ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = -12;
|
||||
|
||||
/**
|
||||
* The CAS Plugin must return ERROR_CAS_DECRYPT if the DescramblerPlugin's
|
||||
* descramble operation fails.
|
||||
*/
|
||||
const int ERROR_CAS_DECRYPT = -13;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_UNKNOWN must be returned when a fatal failure occurs and no
|
||||
* other defined error is appropriate.
|
||||
*/
|
||||
const int ERROR_CAS_UNKNOWN = -14;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_NEED_ACTIVATION is used to trigger device activation process.
|
||||
*/
|
||||
const int ERROR_CAS_NEED_ACTIVATION = -15;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_NEED_PAIRING is used to trigger pairing process.
|
||||
*/
|
||||
const int ERROR_CAS_NEED_PAIRING = -16;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_NO_CARD is used to report no smart card for descrambling.
|
||||
*/
|
||||
const int ERROR_CAS_NO_CARD = -17;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_CARD_MUTE is used to report smart card is muted for
|
||||
* descrambling.
|
||||
*/
|
||||
const int ERROR_CAS_CARD_MUTE = -18;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_CARD_INVALID is used to report smart card isn't valid.
|
||||
*/
|
||||
const int ERROR_CAS_CARD_INVALID = -19;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_BLACKOUT is used to report geographical blackout.
|
||||
*/
|
||||
const int ERROR_CAS_BLACKOUT = -20;
|
||||
|
||||
/**
|
||||
* ERROR_CAS_REBOOTING is used to report CAS is during rebooting.
|
||||
*/
|
||||
const int ERROR_CAS_REBOOTING = -21;
|
||||
}
|
||||
38
cas/aidl/android/hardware/cas/StatusEvent.aidl
Normal file
38
cas/aidl/android/hardware/cas/StatusEvent.aidl
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
/**
|
||||
* The Event Type for status change.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type="byte")
|
||||
enum StatusEvent {
|
||||
/**
|
||||
* The status of CAS plugin was changed due to physical module insertion or
|
||||
* removal. Client must call enumeratePlugins to update plugins' status.
|
||||
*/
|
||||
PLUGIN_PHYSICAL_MODULE_CHANGED,
|
||||
|
||||
/**
|
||||
* The status of supported session number was changed due to physical module
|
||||
* insertion or removal. Client must update session resource according to
|
||||
* latest StatusMessage from the StatusEvent. The plugin supports unlimited
|
||||
* session by default.
|
||||
*/
|
||||
PLUGIN_SESSION_NUMBER_CHANGED,
|
||||
}
|
||||
27
cas/aidl/android/hardware/cas/SubSample.aidl
Normal file
27
cas/aidl/android/hardware/cas/SubSample.aidl
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
/**
|
||||
* A subsample consists of some number of bytes of clear (unscrambled)
|
||||
* data followed by a number of bytes of scrambled data.
|
||||
*/
|
||||
@VintfStability
|
||||
parcelable SubSample {
|
||||
int numBytesOfClearData;
|
||||
int numBytesOfEncryptedData;
|
||||
}
|
||||
93
cas/aidl/default/Android.bp
Executable file
93
cas/aidl/default/Android.bp
Executable file
@@ -0,0 +1,93 @@
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libcasexampleimpl",
|
||||
vendor_available: true,
|
||||
|
||||
srcs: [
|
||||
"CasImpl.cpp",
|
||||
"DescramblerImpl.cpp",
|
||||
"MediaCasService.cpp",
|
||||
"SharedLibrary.cpp",
|
||||
"TypeConvert.cpp",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"android.hardware.cas-V1-ndk",
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
],
|
||||
static_libs: [
|
||||
"libaidlcommonsupport",
|
||||
],
|
||||
header_libs: [
|
||||
"libstagefright_foundation_headers",
|
||||
"media_plugin_headers",
|
||||
],
|
||||
}
|
||||
|
||||
cc_defaults {
|
||||
name: "cas_service_example_defaults",
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
|
||||
srcs: ["service.cpp"],
|
||||
|
||||
static_libs: [
|
||||
"libaidlcommonsupport",
|
||||
"libcasexampleimpl",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.cas-V1-ndk",
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
],
|
||||
header_libs: ["media_plugin_headers"],
|
||||
vintf_fragments: ["android.hardware.cas-service.xml"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.cas-service.example",
|
||||
defaults: ["cas_service_example_defaults"],
|
||||
init_rc: ["cas-default.rc"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.cas-service.example-lazy",
|
||||
defaults: ["cas_service_example_defaults"],
|
||||
init_rc: ["cas-default-lazy.rc"],
|
||||
cflags: ["-DLAZY_SERVICE"],
|
||||
}
|
||||
|
||||
cc_fuzz {
|
||||
name: "android.hardware.cas-service_fuzzer",
|
||||
vendor: true,
|
||||
|
||||
defaults: ["service_fuzzer_defaults"],
|
||||
srcs: ["fuzzer.cpp"],
|
||||
|
||||
shared_libs: [
|
||||
"android.hardware.cas-V1-ndk",
|
||||
"libcutils",
|
||||
"liblog",
|
||||
],
|
||||
static_libs: [
|
||||
"libaidlcommonsupport",
|
||||
"libcasexampleimpl",
|
||||
],
|
||||
header_libs: ["media_plugin_headers"],
|
||||
fuzz_config: {
|
||||
componentid: 1344,
|
||||
},
|
||||
}
|
||||
242
cas/aidl/default/CasImpl.cpp
Executable file
242
cas/aidl/default/CasImpl.cpp
Executable file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
icensed 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_TAG "android.hardware.cas-CasImpl"
|
||||
|
||||
#include <media/cas/CasAPI.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "CasImpl.h"
|
||||
#include "TypeConvert.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
CasImpl::CasImpl(const shared_ptr<ICasListener>& listener) : 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);
|
||||
}
|
||||
|
||||
// static
|
||||
void CasImpl::CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size,
|
||||
const CasSessionId* sessionId) {
|
||||
if (appData == NULL) {
|
||||
ALOGE("Invalid appData!");
|
||||
return;
|
||||
}
|
||||
CasImpl* casImpl = static_cast<CasImpl*>(appData);
|
||||
casImpl->onEvent(sessionId, event, arg, data, size);
|
||||
}
|
||||
|
||||
// static
|
||||
void CasImpl::StatusUpdate(void* appData, int32_t event, int32_t arg) {
|
||||
if (appData == NULL) {
|
||||
ALOGE("Invalid appData!");
|
||||
return;
|
||||
}
|
||||
CasImpl* casImpl = static_cast<CasImpl*>(appData);
|
||||
casImpl->onStatusUpdate(event, arg);
|
||||
}
|
||||
|
||||
void CasImpl::init(CasPlugin* plugin) {
|
||||
shared_ptr<CasPlugin> holder(plugin);
|
||||
atomic_store(&mPluginHolder, holder);
|
||||
}
|
||||
|
||||
void CasImpl::onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size) {
|
||||
if (mListener == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
vector<uint8_t> eventData;
|
||||
if (data != NULL) {
|
||||
eventData.assign(data, data + size);
|
||||
}
|
||||
|
||||
mListener->onEvent(event, arg, eventData);
|
||||
}
|
||||
|
||||
void CasImpl::onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data,
|
||||
size_t size) {
|
||||
if (mListener == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
vector<uint8_t> eventData;
|
||||
if (data != NULL) {
|
||||
eventData.assign(data, data + size);
|
||||
}
|
||||
|
||||
if (sessionId != NULL) {
|
||||
mListener->onSessionEvent(*sessionId, event, arg, eventData);
|
||||
} else {
|
||||
mListener->onEvent(event, arg, eventData);
|
||||
}
|
||||
}
|
||||
|
||||
void CasImpl::onStatusUpdate(int32_t event, int32_t arg) {
|
||||
if (mListener == NULL) {
|
||||
return;
|
||||
}
|
||||
mListener->onStatusUpdate(static_cast<StatusEvent>(event), arg);
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::setPluginStatusUpdateCallback() {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
return toStatus(holder->setStatusCallback(&CasImpl::StatusUpdate));
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::setPrivateData(const vector<uint8_t>& pvtData) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
return toStatus(holder->setPrivateData(pvtData));
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::openSession(SessionIntent intent, ScramblingMode mode,
|
||||
vector<uint8_t>* sessionId) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
status_t err = INVALID_OPERATION;
|
||||
if (holder.get() != nullptr) {
|
||||
err = holder->openSession(static_cast<uint32_t>(intent), static_cast<uint32_t>(mode),
|
||||
sessionId);
|
||||
holder.reset();
|
||||
}
|
||||
|
||||
return toStatus(err);
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::setSessionPrivateData(const vector<uint8_t>& sessionId,
|
||||
const vector<uint8_t>& pvtData) {
|
||||
ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
return toStatus(holder->setSessionPrivateData(sessionId, pvtData));
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::closeSession(const vector<uint8_t>& sessionId) {
|
||||
ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
return toStatus(holder->closeSession(sessionId));
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::processEcm(const vector<uint8_t>& sessionId, const vector<uint8_t>& ecm) {
|
||||
ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
|
||||
return toStatus(holder->processEcm(sessionId, ecm));
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::processEmm(const vector<uint8_t>& emm) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
|
||||
return toStatus(holder->processEmm(emm));
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::sendEvent(int32_t event, int32_t arg, const vector<uint8_t>& eventData) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
|
||||
status_t err = holder->sendEvent(event, arg, eventData);
|
||||
return toStatus(err);
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::sendSessionEvent(const vector<uint8_t>& sessionId, int32_t event,
|
||||
int32_t arg, const vector<uint8_t>& eventData) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
|
||||
status_t err = holder->sendSessionEvent(sessionId, event, arg, eventData);
|
||||
return toStatus(err);
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::provision(const string& provisionString) {
|
||||
ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str());
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
|
||||
return toStatus(holder->provision(String8(provisionString.c_str())));
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::refreshEntitlements(int32_t refreshType,
|
||||
const vector<uint8_t>& refreshData) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
|
||||
status_t err = holder->refreshEntitlements(refreshType, refreshData);
|
||||
return toStatus(err);
|
||||
}
|
||||
|
||||
ScopedAStatus CasImpl::release() {
|
||||
ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get());
|
||||
|
||||
shared_ptr<CasPlugin> holder(nullptr);
|
||||
atomic_store(&mPluginHolder, holder);
|
||||
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
93
cas/aidl/default/CasImpl.h
Executable file
93
cas/aidl/default/CasImpl.h
Executable file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#include <aidl/android/hardware/cas/BnCas.h>
|
||||
#include <aidl/android/hardware/cas/ICasListener.h>
|
||||
#include <media/stagefright/foundation/ABase.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
using namespace ::android;
|
||||
using namespace std;
|
||||
using ndk::ScopedAStatus;
|
||||
|
||||
class CasImpl : public BnCas {
|
||||
public:
|
||||
CasImpl(const shared_ptr<ICasListener>& listener);
|
||||
virtual ~CasImpl();
|
||||
|
||||
static void OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size);
|
||||
|
||||
static void CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size,
|
||||
const CasSessionId* sessionId);
|
||||
|
||||
static void StatusUpdate(void* appData, int32_t event, int32_t arg);
|
||||
|
||||
void init(CasPlugin* plugin);
|
||||
void onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size);
|
||||
|
||||
void onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data,
|
||||
size_t size);
|
||||
|
||||
void onStatusUpdate(int32_t event, int32_t arg);
|
||||
|
||||
// ICas inherits
|
||||
|
||||
ScopedAStatus setPluginStatusUpdateCallback();
|
||||
|
||||
virtual ScopedAStatus setPrivateData(const vector<uint8_t>& pvtData) override;
|
||||
|
||||
virtual ScopedAStatus openSession(SessionIntent intent, ScramblingMode mode,
|
||||
vector<uint8_t>* sessionId) override;
|
||||
|
||||
virtual ScopedAStatus closeSession(const vector<uint8_t>& sessionId) override;
|
||||
|
||||
virtual ScopedAStatus setSessionPrivateData(const vector<uint8_t>& sessionId,
|
||||
const vector<uint8_t>& pvtData) override;
|
||||
|
||||
virtual ScopedAStatus processEcm(const vector<uint8_t>& sessionId,
|
||||
const vector<uint8_t>& ecm) override;
|
||||
|
||||
virtual ScopedAStatus processEmm(const vector<uint8_t>& emm) override;
|
||||
|
||||
virtual ScopedAStatus sendEvent(int32_t event, int32_t arg,
|
||||
const vector<uint8_t>& eventData) override;
|
||||
|
||||
virtual ScopedAStatus sendSessionEvent(const vector<uint8_t>& sessionId, int32_t event,
|
||||
int32_t arg, const vector<uint8_t>& eventData) override;
|
||||
|
||||
virtual ScopedAStatus provision(const string& provisionString) override;
|
||||
|
||||
virtual ScopedAStatus refreshEntitlements(int32_t refreshType,
|
||||
const vector<uint8_t>& refreshData) override;
|
||||
|
||||
virtual ScopedAStatus release() override;
|
||||
|
||||
private:
|
||||
struct PluginHolder;
|
||||
shared_ptr<CasPlugin> mPluginHolder;
|
||||
shared_ptr<ICasListener> mListener;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
|
||||
};
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
193
cas/aidl/default/DescramblerImpl.cpp
Executable file
193
cas/aidl/default/DescramblerImpl.cpp
Executable file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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_TAG "android.hardware.cas-DescramblerImpl"
|
||||
|
||||
#include <aidlcommonsupport/NativeHandle.h>
|
||||
#include <inttypes.h>
|
||||
#include <media/cas/DescramblerAPI.h>
|
||||
#include <media/hardware/CryptoAPI.h>
|
||||
#include <media/stagefright/foundation/AUtils.h>
|
||||
#include <sys/mman.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "DescramblerImpl.h"
|
||||
#include "TypeConvert.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
#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(DescramblerPlugin* plugin) : mPluginHolder(plugin) {
|
||||
ALOGV("CTOR: plugin=%p", mPluginHolder.get());
|
||||
}
|
||||
|
||||
DescramblerImpl::~DescramblerImpl() {
|
||||
ALOGV("DTOR: plugin=%p", mPluginHolder.get());
|
||||
release();
|
||||
}
|
||||
|
||||
ScopedAStatus DescramblerImpl::setMediaCasSession(const vector<uint8_t>& in_sessionId) {
|
||||
ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(in_sessionId).string());
|
||||
|
||||
shared_ptr<DescramblerPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
|
||||
return toStatus(holder->setMediaCasSession(in_sessionId));
|
||||
}
|
||||
|
||||
ScopedAStatus DescramblerImpl::requiresSecureDecoderComponent(const string& in_mime,
|
||||
bool* _aidl_return) {
|
||||
shared_ptr<DescramblerPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
*_aidl_return = false;
|
||||
}
|
||||
|
||||
*_aidl_return = holder->requiresSecureDecoderComponent(String8(in_mime.c_str()));
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
static inline bool validateRangeForSize(int64_t offset, int64_t length, int64_t size) {
|
||||
return isInRange<int64_t, uint64_t>(0, (uint64_t)size, offset, (uint64_t)length);
|
||||
}
|
||||
|
||||
ScopedAStatus DescramblerImpl::descramble(ScramblingControl scramblingControl,
|
||||
const vector<SubSample>& subSamples,
|
||||
const SharedBuffer& srcBuffer, int64_t srcOffset,
|
||||
const DestinationBuffer& dstBuffer, int64_t dstOffset,
|
||||
int32_t* _aidl_return) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
|
||||
// heapbase's size is stored in int64_t, but mapMemory's mmap will map size in
|
||||
// size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed but the
|
||||
// mapped memory's actual size will be smaller than the reported size.
|
||||
if (srcBuffer.heapBase.size > SIZE_MAX) {
|
||||
ALOGE("Invalid memory size: %" PRIu64 "", srcBuffer.heapBase.size);
|
||||
android_errorWriteLog(0x534e4554, "79376389");
|
||||
return toStatus(BAD_VALUE);
|
||||
}
|
||||
|
||||
void* srcPtr = mmap(NULL, srcBuffer.heapBase.size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
srcBuffer.heapBase.fd.get(), 0);
|
||||
|
||||
// Validate if the offset and size in the SharedBuffer is consistent with the
|
||||
// mapped heapbase, since the offset and size is controlled by client.
|
||||
if (srcPtr == NULL) {
|
||||
ALOGE("Failed to map src buffer.");
|
||||
return toStatus(BAD_VALUE);
|
||||
}
|
||||
if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, srcBuffer.heapBase.size)) {
|
||||
ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64
|
||||
", srcMem"
|
||||
"size %" PRIu64 "",
|
||||
srcBuffer.offset, srcBuffer.size, srcBuffer.heapBase.size);
|
||||
android_errorWriteLog(0x534e4554, "67962232");
|
||||
return toStatus(BAD_VALUE);
|
||||
}
|
||||
|
||||
// use 64-bit here to catch bad subsample size that might be overflowing.
|
||||
uint64_t totalBytesInSubSamples = 0;
|
||||
for (size_t i = 0; i < subSamples.size(); i++) {
|
||||
uint32_t numBytesOfClearData = subSamples[i].numBytesOfClearData;
|
||||
uint32_t numBytesOfEncryptedData = subSamples[i].numBytesOfEncryptedData;
|
||||
totalBytesInSubSamples += (uint64_t)numBytesOfClearData + numBytesOfEncryptedData;
|
||||
}
|
||||
// Further validate if the specified srcOffset and requested total subsample size
|
||||
// is consistent with the source shared buffer size.
|
||||
if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
|
||||
ALOGE("Invalid srcOffset and subsample size: "
|
||||
"srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64
|
||||
", srcBuffer"
|
||||
"size %" PRIu64 "",
|
||||
srcOffset, totalBytesInSubSamples, srcBuffer.size);
|
||||
android_errorWriteLog(0x534e4554, "67962232");
|
||||
return toStatus(BAD_VALUE);
|
||||
}
|
||||
srcPtr = (uint8_t*)srcPtr + srcBuffer.offset;
|
||||
|
||||
void* dstPtr = NULL;
|
||||
if (dstBuffer.getTag() == DestinationBuffer::Tag::nonsecureMemory) {
|
||||
// When using shared memory, src buffer is also used as dst,
|
||||
// we don't map it again here.
|
||||
dstPtr = srcPtr;
|
||||
|
||||
// In this case the dst and src would be the same buffer, need to validate
|
||||
// dstOffset against the buffer size too.
|
||||
if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
|
||||
ALOGE("Invalid dstOffset and subsample size: "
|
||||
"dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64
|
||||
", srcBuffer"
|
||||
"size %" PRIu64 "",
|
||||
dstOffset, totalBytesInSubSamples, srcBuffer.size);
|
||||
android_errorWriteLog(0x534e4554, "67962232");
|
||||
return toStatus(BAD_VALUE);
|
||||
}
|
||||
} else {
|
||||
native_handle_t* handle = makeFromAidl(dstBuffer.get<DestinationBuffer::secureMemory>());
|
||||
dstPtr = static_cast<void*>(handle);
|
||||
}
|
||||
|
||||
// Get a local copy of the shared_ptr for the plugin. Note that before
|
||||
// calling the callback, this shared_ptr must be manually reset, since
|
||||
// the client side could proceed as soon as the callback is called
|
||||
// without waiting for this method to go out of scope.
|
||||
shared_ptr<DescramblerPlugin> holder = atomic_load(&mPluginHolder);
|
||||
if (holder.get() == nullptr) {
|
||||
return toStatus(INVALID_OPERATION);
|
||||
}
|
||||
|
||||
// Casting SubSample to DescramblerPlugin::SubSample, but need to ensure
|
||||
// structs are actually identical
|
||||
|
||||
auto returnStatus =
|
||||
holder->descramble(dstBuffer.getTag() != DestinationBuffer::Tag::nonsecureMemory,
|
||||
(DescramblerPlugin::ScramblingControl)scramblingControl,
|
||||
subSamples.size(), (DescramblerPlugin::SubSample*)subSamples.data(),
|
||||
srcPtr, srcOffset, dstPtr, dstOffset, NULL);
|
||||
|
||||
holder.reset();
|
||||
*_aidl_return = returnStatus;
|
||||
return toStatus(returnStatus >= 0 ? OK : returnStatus);
|
||||
}
|
||||
|
||||
ScopedAStatus DescramblerImpl::release() {
|
||||
ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get());
|
||||
|
||||
shared_ptr<DescramblerPlugin> holder(nullptr);
|
||||
atomic_store(&mPluginHolder, holder);
|
||||
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
56
cas/aidl/default/DescramblerImpl.h
Executable file
56
cas/aidl/default/DescramblerImpl.h
Executable file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#include <aidl/android/hardware/cas/BnDescrambler.h>
|
||||
#include <media/stagefright/foundation/ABase.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
using namespace ::android;
|
||||
using namespace std;
|
||||
using ndk::ScopedAStatus;
|
||||
|
||||
class DescramblerImpl : public BnDescrambler {
|
||||
public:
|
||||
DescramblerImpl(DescramblerPlugin* plugin);
|
||||
virtual ~DescramblerImpl();
|
||||
|
||||
virtual ScopedAStatus setMediaCasSession(const vector<uint8_t>& in_sessionId) override;
|
||||
|
||||
virtual ScopedAStatus requiresSecureDecoderComponent(const string& in_mime,
|
||||
bool* _aidl_return) override;
|
||||
|
||||
virtual ScopedAStatus descramble(ScramblingControl in_scramblingControl,
|
||||
const vector<SubSample>& in_subSamples,
|
||||
const SharedBuffer& in_srcBuffer, int64_t in_srcOffset,
|
||||
const DestinationBuffer& in_dstBuffer, int64_t in_dstOffset,
|
||||
int32_t* _aidl_return) override;
|
||||
|
||||
virtual ScopedAStatus release() override;
|
||||
|
||||
private:
|
||||
shared_ptr<DescramblerPlugin> mPluginHolder;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl);
|
||||
};
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
219
cas/aidl/default/FactoryLoader.h
Executable file
219
cas/aidl/default/FactoryLoader.h
Executable file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <media/cas/CasAPI.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include "SharedLibrary.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
using namespace ::android;
|
||||
|
||||
template <class T>
|
||||
class FactoryLoader {
|
||||
public:
|
||||
FactoryLoader(const char* name) : mFactory(NULL), mCreateFactoryFuncName(name) {}
|
||||
|
||||
virtual ~FactoryLoader() { closeFactory(); }
|
||||
|
||||
bool findFactoryForScheme(int32_t CA_system_id, shared_ptr<SharedLibrary>* library = NULL,
|
||||
T** factory = NULL);
|
||||
|
||||
bool enumeratePlugins(vector<AidlCasPluginDescriptor>* results);
|
||||
|
||||
private:
|
||||
typedef T* (*CreateFactoryFunc)();
|
||||
|
||||
Mutex mMapLock;
|
||||
T* mFactory;
|
||||
const char* mCreateFactoryFuncName;
|
||||
shared_ptr<SharedLibrary> mLibrary;
|
||||
KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
|
||||
KeyedVector<String8, shared_ptr<SharedLibrary>> mLibraryPathToOpenLibraryMap;
|
||||
|
||||
bool loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
|
||||
shared_ptr<SharedLibrary>* library, T** factory);
|
||||
|
||||
bool queryPluginsFromPath(const String8& path, vector<AidlCasPluginDescriptor>* results);
|
||||
|
||||
bool openFactory(const String8& path);
|
||||
void closeFactory();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
bool FactoryLoader<T>::findFactoryForScheme(int32_t CA_system_id,
|
||||
shared_ptr<SharedLibrary>* library, T** factory) {
|
||||
if (library != NULL) {
|
||||
library->reset();
|
||||
}
|
||||
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
|
||||
#ifdef __LP64__
|
||||
String8 dirPath("/vendor/lib64/mediacas");
|
||||
#else
|
||||
String8 dirPath("/vendor/lib/mediacas");
|
||||
#endif
|
||||
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<AidlCasPluginDescriptor>* results) {
|
||||
ALOGI("enumeratePlugins");
|
||||
|
||||
results->clear();
|
||||
|
||||
#ifdef __LP64__
|
||||
String8 dirPath("/vendor/lib64/mediacas");
|
||||
#else
|
||||
String8 dirPath("/vendor/lib/mediacas");
|
||||
#endif
|
||||
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,
|
||||
shared_ptr<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<AidlCasPluginDescriptor>* 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(
|
||||
AidlCasPluginDescriptor{.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];
|
||||
} else {
|
||||
index = mLibraryPathToOpenLibraryMap.add(path, NULL);
|
||||
}
|
||||
|
||||
if (!mLibrary.get()) {
|
||||
mLibrary = ::ndk::SharedRefBase::make<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.reset();
|
||||
}
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
101
cas/aidl/default/MediaCasService.cpp
Executable file
101
cas/aidl/default/MediaCasService.cpp
Executable file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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_TAG "android.hardware.cas-MediaCasService"
|
||||
|
||||
#include <media/cas/CasAPI.h>
|
||||
#include <media/cas/DescramblerAPI.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "CasImpl.h"
|
||||
#include "DescramblerImpl.h"
|
||||
#include "MediaCasService.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
MediaCasService::MediaCasService()
|
||||
: mCasLoader("createCasFactory"), mDescramblerLoader("createDescramblerFactory") {}
|
||||
|
||||
MediaCasService::~MediaCasService() {}
|
||||
|
||||
ScopedAStatus MediaCasService::enumeratePlugins(
|
||||
vector<AidlCasPluginDescriptor>* aidlCasPluginDescriptors) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
|
||||
mCasLoader.enumeratePlugins(aidlCasPluginDescriptors);
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus MediaCasService::isSystemIdSupported(int32_t CA_system_id, bool* _aidl_return) {
|
||||
ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id);
|
||||
|
||||
*_aidl_return = mCasLoader.findFactoryForScheme(CA_system_id);
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus MediaCasService::createPlugin(int32_t CA_system_id,
|
||||
const shared_ptr<ICasListener>& listener,
|
||||
shared_ptr<ICas>* _aidl_return) {
|
||||
ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
|
||||
if (listener == NULL) ALOGV("%s: Listener is NULL", __FUNCTION__);
|
||||
|
||||
CasFactory* factory;
|
||||
shared_ptr<SharedLibrary> library;
|
||||
if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) {
|
||||
CasPlugin* plugin = NULL;
|
||||
shared_ptr<CasImpl> casImpl = ::ndk::SharedRefBase::make<CasImpl>(listener);
|
||||
if (factory->createPlugin(CA_system_id, casImpl.get(), &CasImpl::CallBackExt, &plugin) ==
|
||||
OK &&
|
||||
plugin != NULL) {
|
||||
casImpl->init(plugin);
|
||||
*_aidl_return = casImpl;
|
||||
casImpl->setPluginStatusUpdateCallback();
|
||||
}
|
||||
}
|
||||
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus MediaCasService::isDescramblerSupported(int32_t CA_system_id, bool* _aidl_return) {
|
||||
ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
|
||||
|
||||
*_aidl_return = mDescramblerLoader.findFactoryForScheme(CA_system_id);
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus MediaCasService::createDescrambler(int32_t CA_system_id,
|
||||
shared_ptr<IDescrambler>* _aidl_return) {
|
||||
ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
|
||||
|
||||
DescramblerFactory* factory;
|
||||
shared_ptr<SharedLibrary> library;
|
||||
if (mDescramblerLoader.findFactoryForScheme(CA_system_id, &library, &factory)) {
|
||||
DescramblerPlugin* plugin = NULL;
|
||||
if (factory->createPlugin(CA_system_id, &plugin) == OK && plugin != NULL) {
|
||||
*_aidl_return = ::ndk::SharedRefBase::make<DescramblerImpl>(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
59
cas/aidl/default/MediaCasService.h
Executable file
59
cas/aidl/default/MediaCasService.h
Executable file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
#include <aidl/android/hardware/cas/BnMediaCasService.h>
|
||||
#include <media/cas/DescramblerAPI.h>
|
||||
|
||||
#include "FactoryLoader.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
using namespace ::android;
|
||||
using namespace std;
|
||||
using ndk::ScopedAStatus;
|
||||
|
||||
class MediaCasService : public BnMediaCasService {
|
||||
public:
|
||||
MediaCasService();
|
||||
|
||||
virtual ScopedAStatus enumeratePlugins(
|
||||
vector<AidlCasPluginDescriptor>* aidlCasPluginDescriptors) override;
|
||||
|
||||
virtual ScopedAStatus isSystemIdSupported(int32_t in_CA_system_id, bool* _aidl_return) override;
|
||||
|
||||
virtual ScopedAStatus createPlugin(int32_t in_CA_system_id,
|
||||
const shared_ptr<ICasListener>& in_listener,
|
||||
shared_ptr<ICas>* _aidl_return) override;
|
||||
|
||||
virtual ScopedAStatus isDescramblerSupported(int32_t in_CA_system_id,
|
||||
bool* _aidl_return) override;
|
||||
|
||||
virtual ScopedAStatus createDescrambler(int32_t in_CA_system_id,
|
||||
shared_ptr<IDescrambler>* _aidl_return) override;
|
||||
|
||||
private:
|
||||
FactoryLoader<CasFactory> mCasLoader;
|
||||
FactoryLoader<DescramblerFactory> mDescramblerLoader;
|
||||
|
||||
virtual ~MediaCasService();
|
||||
};
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
3
cas/aidl/default/OWNERS
Executable file
3
cas/aidl/default/OWNERS
Executable file
@@ -0,0 +1,3 @@
|
||||
# Bug component: 1344
|
||||
quxiangfang@google.com
|
||||
hgchen@google.com
|
||||
61
cas/aidl/default/SharedLibrary.cpp
Executable file
61
cas/aidl/default/SharedLibrary.cpp
Executable file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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_TAG "android.hardware.cas-SharedLibrary"
|
||||
|
||||
#include "SharedLibrary.h"
|
||||
#include <dlfcn.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
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 cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
45
cas/aidl/default/SharedLibrary.h
Executable file
45
cas/aidl/default/SharedLibrary.h
Executable file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#include <android/binder_interface_utils.h>
|
||||
#include <media/stagefright/foundation/ABase.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
using namespace ::android;
|
||||
|
||||
class SharedLibrary : public ndk::SharedRefBase {
|
||||
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 cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
110
cas/aidl/default/TypeConvert.cpp
Executable file
110
cas/aidl/default/TypeConvert.cpp
Executable file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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_TAG "android.hardware.cas-TypeConvert"
|
||||
|
||||
#include <aidl/android/hardware/cas/Status.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "TypeConvert.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
ScopedAStatus toStatus(status_t legacyStatus) {
|
||||
int status;
|
||||
switch (legacyStatus) {
|
||||
case OK:
|
||||
return ndk::ScopedAStatus::ok();
|
||||
case ERROR_CAS_NO_LICENSE:
|
||||
status = Status::ERROR_CAS_NO_LICENSE;
|
||||
break;
|
||||
case ERROR_CAS_LICENSE_EXPIRED:
|
||||
status = Status::ERROR_CAS_LICENSE_EXPIRED;
|
||||
break;
|
||||
case ERROR_CAS_SESSION_NOT_OPENED:
|
||||
status = Status::ERROR_CAS_SESSION_NOT_OPENED;
|
||||
break;
|
||||
case ERROR_CAS_CANNOT_HANDLE:
|
||||
status = Status::ERROR_CAS_CANNOT_HANDLE;
|
||||
break;
|
||||
case ERROR_CAS_TAMPER_DETECTED:
|
||||
status = Status::ERROR_CAS_INVALID_STATE;
|
||||
break;
|
||||
case BAD_VALUE:
|
||||
status = Status::BAD_VALUE;
|
||||
break;
|
||||
case ERROR_CAS_NOT_PROVISIONED:
|
||||
status = Status::ERROR_CAS_NOT_PROVISIONED;
|
||||
break;
|
||||
case ERROR_CAS_RESOURCE_BUSY:
|
||||
status = Status::ERROR_CAS_RESOURCE_BUSY;
|
||||
break;
|
||||
case ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION:
|
||||
status = Status::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION;
|
||||
break;
|
||||
case ERROR_CAS_DEVICE_REVOKED:
|
||||
status = Status::ERROR_CAS_DEVICE_REVOKED;
|
||||
break;
|
||||
case ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED:
|
||||
status = Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED;
|
||||
break;
|
||||
case ERROR_CAS_DECRYPT:
|
||||
status = Status::ERROR_CAS_DECRYPT;
|
||||
break;
|
||||
case ERROR_CAS_NEED_ACTIVATION:
|
||||
status = Status::ERROR_CAS_NEED_ACTIVATION;
|
||||
break;
|
||||
case ERROR_CAS_NEED_PAIRING:
|
||||
status = Status::ERROR_CAS_NEED_PAIRING;
|
||||
break;
|
||||
case ERROR_CAS_NO_CARD:
|
||||
status = Status::ERROR_CAS_NO_CARD;
|
||||
break;
|
||||
case ERROR_CAS_CARD_MUTE:
|
||||
status = Status::ERROR_CAS_CARD_MUTE;
|
||||
break;
|
||||
case ERROR_CAS_CARD_INVALID:
|
||||
status = Status::ERROR_CAS_CARD_INVALID;
|
||||
break;
|
||||
case ERROR_CAS_BLACKOUT:
|
||||
status = Status::ERROR_CAS_BLACKOUT;
|
||||
break;
|
||||
default:
|
||||
ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN", legacyStatus);
|
||||
status = Status::ERROR_CAS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return ScopedAStatus::fromServiceSpecificError(status);
|
||||
}
|
||||
|
||||
String8 sessionIdToString(const std::vector<uint8_t>& sessionId) {
|
||||
String8 result;
|
||||
for (auto it = sessionId.begin(); it != sessionId.end(); it++) {
|
||||
result.appendFormat("%02x ", *it);
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
result.append("(null)");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
36
cas/aidl/default/TypeConvert.h
Executable file
36
cas/aidl/default/TypeConvert.h
Executable file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#include <android/binder_interface_utils.h>
|
||||
#include <media/stagefright/MediaErrors.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace cas {
|
||||
|
||||
using namespace ::android;
|
||||
using ndk::ScopedAStatus;
|
||||
|
||||
ScopedAStatus toStatus(status_t legacyStatus);
|
||||
|
||||
String8 sessionIdToString(const std::vector<uint8_t>& sessionId);
|
||||
|
||||
} // namespace cas
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
6
cas/aidl/default/android.hardware.cas-service.xml
Executable file
6
cas/aidl/default/android.hardware.cas-service.xml
Executable file
@@ -0,0 +1,6 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.cas</name>
|
||||
<fqname>IMediaCasService/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
9
cas/aidl/default/cas-default-lazy.rc
Executable file
9
cas/aidl/default/cas-default-lazy.rc
Executable file
@@ -0,0 +1,9 @@
|
||||
service vendor.cas-default-lazy /vendor/bin/hw/android.hardware.cas-service.example-lazy
|
||||
interface aidl android.hardware.cas.IMediaCasService/default
|
||||
class hal
|
||||
user media
|
||||
group mediadrm drmrpc
|
||||
ioprio rt 4
|
||||
task_profiles ProcessCapacityHigh
|
||||
oneshot
|
||||
disabled
|
||||
7
cas/aidl/default/cas-default.rc
Executable file
7
cas/aidl/default/cas-default.rc
Executable file
@@ -0,0 +1,7 @@
|
||||
service vendor.cas-default /vendor/bin/hw/android.hardware.cas-service.example
|
||||
interface aidl android.hardware.cas.IMediaCasService/default
|
||||
class hal
|
||||
user media
|
||||
group mediadrm drmrpc
|
||||
ioprio rt 4
|
||||
task_profiles ProcessCapacityHigh
|
||||
30
cas/aidl/default/fuzzer.cpp
Executable file
30
cas/aidl/default/fuzzer.cpp
Executable file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
#include <MediaCasService.h>
|
||||
#include <fuzzbinder/libbinder_ndk_driver.h>
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
|
||||
using aidl::android::hardware::cas::MediaCasService;
|
||||
using android::fuzzService;
|
||||
using ndk::SharedRefBase;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
auto mediaCasServiceAidl = SharedRefBase::make<MediaCasService>();
|
||||
|
||||
fuzzService(mediaCasServiceAidl->asBinder().get(), FuzzedDataProvider(data, size));
|
||||
|
||||
return 0;
|
||||
}
|
||||
50
cas/aidl/default/service.cpp
Executable file
50
cas/aidl/default/service.cpp
Executable file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2022 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.
|
||||
*/
|
||||
|
||||
#ifdef LAZY_SERVICE
|
||||
const bool kLazyService = true;
|
||||
#define LOG_TAG "android.hardware.cas-service.example-lazy"
|
||||
#else
|
||||
const bool kLazyService = false;
|
||||
#define LOG_TAG "android.hardware.cas-service.example"
|
||||
#endif
|
||||
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
#include "MediaCasService.h"
|
||||
|
||||
using aidl::android::hardware::cas::MediaCasService;
|
||||
|
||||
int main() {
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(8);
|
||||
|
||||
// Setup hwbinder service
|
||||
std::shared_ptr<MediaCasService> service = ::ndk::SharedRefBase::make<MediaCasService>();
|
||||
|
||||
const std::string instance = std::string() + MediaCasService::descriptor + "/default";
|
||||
binder_status_t status;
|
||||
|
||||
if (kLazyService) {
|
||||
status = AServiceManager_registerLazyService(service->asBinder().get(), instance.c_str());
|
||||
} else {
|
||||
status = AServiceManager_addService(service->asBinder().get(), instance.c_str());
|
||||
}
|
||||
LOG_ALWAYS_FATAL_IF(status != STATUS_OK, "Error while registering cas service: %d", status);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return 0;
|
||||
}
|
||||
45
cas/aidl/vts/functional/Android.bp
Normal file
45
cas/aidl/vts/functional/Android.bp
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Copyright (C) 2022 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 {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "VtsHalCasAidlTargetTest",
|
||||
defaults: [
|
||||
"VtsHalTargetTestDefaults",
|
||||
"use_libaidlvintf_gtest_helper_static",
|
||||
],
|
||||
srcs: ["VtsHalCasAidlTargetTest.cpp"],
|
||||
static_libs: [
|
||||
"android.hardware.cas-V1-ndk",
|
||||
"android.hardware.common-V2-ndk",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
],
|
||||
test_suites: [
|
||||
"general-tests",
|
||||
"vts",
|
||||
],
|
||||
disable_framework: true,
|
||||
}
|
||||
3
cas/aidl/vts/functional/OWNERS
Normal file
3
cas/aidl/vts/functional/OWNERS
Normal file
@@ -0,0 +1,3 @@
|
||||
# Bug component: 1344
|
||||
quxiangfang@google.com
|
||||
hgchen@google.com
|
||||
809
cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp
Normal file
809
cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp
Normal file
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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_TAG "mediacas_aidl_hal_test"
|
||||
|
||||
#include <aidl/Gtest.h>
|
||||
#include <aidl/Vintf.h>
|
||||
#include <aidl/android/hardware/cas/BnCasListener.h>
|
||||
#include <aidl/android/hardware/cas/IMediaCasService.h>
|
||||
#include <aidl/android/hardware/cas/Status.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
#include <binder/ParcelFileDescriptor.h>
|
||||
#include <cutils/ashmem.h>
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
#define CLEAR_KEY_SYSTEM_ID 0xF6D8
|
||||
#define INVALID_SYSTEM_ID 0
|
||||
#define WAIT_TIMEOUT 3000000000
|
||||
|
||||
#define PROVISION_STR \
|
||||
"{ " \
|
||||
" \"id\": 21140844, " \
|
||||
" \"name\": \"Test Title\", " \
|
||||
" \"lowercase_organization_name\": \"Android\", " \
|
||||
" \"asset_key\": { " \
|
||||
" \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\" " \
|
||||
" }, " \
|
||||
" \"cas_type\": 1, " \
|
||||
" \"track_types\": [ ] " \
|
||||
"} "
|
||||
|
||||
using aidl::android::hardware::common::Ashmem;
|
||||
using android::Mutex;
|
||||
using namespace aidl::android::hardware::cas;
|
||||
using namespace ndk;
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
const uint8_t kEcmBinaryBuffer[] = {
|
||||
0x00, 0x00, 0x01, 0xf0, 0x00, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00,
|
||||
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00,
|
||||
0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0x0e, 0xe3, 0x91, 0xbc, 0xfd, 0x05, 0xb1, 0x60, 0x4f,
|
||||
0x17, 0x82, 0xa4, 0x86, 0x9b, 0x23, 0x56, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x27, 0x10, 0x02, 0x00, 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0xd7, 0x43, 0x62, 0xf8, 0x1c,
|
||||
0x62, 0x19, 0x05, 0xc7, 0x3a, 0x42, 0xcd, 0xfd, 0xd9, 0x13, 0x48,
|
||||
};
|
||||
|
||||
const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}};
|
||||
|
||||
const uint8_t kInBinaryBuffer[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
|
||||
0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
|
||||
0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
|
||||
0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
|
||||
0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
|
||||
0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
|
||||
0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
|
||||
0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
|
||||
0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
|
||||
0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
|
||||
0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x6e, 0x45, 0x21,
|
||||
0x82, 0x38, 0xf0, 0x9d, 0x7d, 0x96, 0xe6, 0x94, 0xae, 0xe2, 0x87, 0x8f, 0x04, 0x49, 0xe5,
|
||||
0xf6, 0x8c, 0x8b, 0x9a, 0x10, 0x18, 0xba, 0x94, 0xe9, 0x22, 0x31, 0x04, 0x7e, 0x60, 0x5b,
|
||||
0xc4, 0x24, 0x00, 0x90, 0x62, 0x0d, 0xdc, 0x85, 0x74, 0x75, 0x78, 0xd0, 0x14, 0x08, 0xcb,
|
||||
0x02, 0x1d, 0x7d, 0x9d, 0x34, 0xe8, 0x81, 0xb9, 0xf7, 0x09, 0x28, 0x79, 0x29, 0x8d, 0xe3,
|
||||
0x14, 0xed, 0x5f, 0xca, 0xaf, 0xf4, 0x1c, 0x49, 0x15, 0xe1, 0x80, 0x29, 0x61, 0x76, 0x80,
|
||||
0x43, 0xf8, 0x58, 0x53, 0x40, 0xd7, 0x31, 0x6d, 0x61, 0x81, 0x41, 0xe9, 0x77, 0x9f, 0x9c,
|
||||
0xe1, 0x6d, 0xf2, 0xee, 0xd9, 0xc8, 0x67, 0xd2, 0x5f, 0x48, 0x73, 0xe3, 0x5c, 0xcd, 0xa7,
|
||||
0x45, 0x58, 0xbb, 0xdd, 0x28, 0x1d, 0x68, 0xfc, 0xb4, 0xc6, 0xf6, 0x92, 0xf6, 0x30, 0x03,
|
||||
0xaa, 0xe4, 0x32, 0xf6, 0x34, 0x51, 0x4b, 0x0f, 0x8c, 0xf9, 0xac, 0x98, 0x22, 0xfb, 0x49,
|
||||
0xc8, 0xbf, 0xca, 0x8c, 0x80, 0x86, 0x5d, 0xd7, 0xa4, 0x52, 0xb1, 0xd9, 0xa6, 0x04, 0x4e,
|
||||
0xb3, 0x2d, 0x1f, 0xb8, 0x35, 0xcc, 0x45, 0x6d, 0x9c, 0x20, 0xa7, 0xa4, 0x34, 0x59, 0x72,
|
||||
0xe3, 0xae, 0xba, 0x49, 0xde, 0xd1, 0xaa, 0xee, 0x3d, 0x77, 0xfc, 0x5d, 0xc6, 0x1f, 0x9d,
|
||||
0xac, 0xc2, 0x15, 0x66, 0xb8, 0xe1, 0x54, 0x4e, 0x74, 0x93, 0xdb, 0x9a, 0x24, 0x15, 0x6e,
|
||||
0x20, 0xa3, 0x67, 0x3e, 0x5a, 0x24, 0x41, 0x5e, 0xb0, 0xe6, 0x35, 0x87, 0x1b, 0xc8, 0x7a,
|
||||
0xf9, 0x77, 0x65, 0xe0, 0x01, 0xf2, 0x4c, 0xe4, 0x2b, 0xa9, 0x64, 0x96, 0x96, 0x0b, 0x46,
|
||||
0xca, 0xea, 0x79, 0x0e, 0x78, 0xa3, 0x5f, 0x43, 0xfc, 0x47, 0x6a, 0x12, 0xfa, 0xc4, 0x33,
|
||||
0x0e, 0x88, 0x1c, 0x19, 0x3a, 0x00, 0xc3, 0x4e, 0xb5, 0xd8, 0xfa, 0x8e, 0xf1, 0xbc, 0x3d,
|
||||
0xb2, 0x7e, 0x50, 0x8d, 0x67, 0xc3, 0x6b, 0xed, 0xe2, 0xea, 0xa6, 0x1f, 0x25, 0x24, 0x7c,
|
||||
0x94, 0x74, 0x50, 0x49, 0xe3, 0xc6, 0x58, 0x2e, 0xfd, 0x28, 0xb4, 0xc6, 0x73, 0xb1, 0x53,
|
||||
0x74, 0x27, 0x94, 0x5c, 0xdf, 0x69, 0xb7, 0xa1, 0xd7, 0xf5, 0xd3, 0x8a, 0x2c, 0x2d, 0xb4,
|
||||
0x5e, 0x8a, 0x16, 0x14, 0x54, 0x64, 0x6e, 0x00, 0x6b, 0x11, 0x59, 0x8a, 0x63, 0x38, 0x80,
|
||||
0x76, 0xc3, 0xd5, 0x59, 0xf7, 0x3f, 0xd2, 0xfa, 0xa5, 0xca, 0x82, 0xff, 0x4a, 0x62, 0xf0,
|
||||
0xe3, 0x42, 0xf9, 0x3b, 0x38, 0x27, 0x8a, 0x89, 0xaa, 0x50, 0x55, 0x4b, 0x29, 0xf1, 0x46,
|
||||
0x7c, 0x75, 0xef, 0x65, 0xaf, 0x9b, 0x0d, 0x6d, 0xda, 0x25, 0x94, 0x14, 0xc1, 0x1b, 0xf0,
|
||||
0xc5, 0x4c, 0x24, 0x0e, 0x65,
|
||||
};
|
||||
|
||||
const uint8_t kOutRefBinaryBuffer[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
|
||||
0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
|
||||
0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
|
||||
0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
|
||||
0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
|
||||
0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
|
||||
0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
|
||||
0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
|
||||
0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
|
||||
0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
|
||||
0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
|
||||
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
|
||||
0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
|
||||
0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
|
||||
0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
|
||||
0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
|
||||
0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
|
||||
0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
|
||||
0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
|
||||
0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
|
||||
0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
|
||||
0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
|
||||
0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
|
||||
0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
|
||||
0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
|
||||
0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
|
||||
0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
|
||||
0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
|
||||
0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
|
||||
0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
|
||||
0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
|
||||
0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
|
||||
0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
|
||||
0x73, 0x63, 0x65, 0x6e, 0x65,
|
||||
};
|
||||
|
||||
class MediaCasListener : public BnCasListener {
|
||||
public:
|
||||
virtual ScopedAStatus onEvent(int32_t event, int32_t arg,
|
||||
const vector<uint8_t>& data) override {
|
||||
Mutex::Autolock autoLock(mMsgLock);
|
||||
mEvent = event;
|
||||
mEventArg = arg;
|
||||
mEventData = data;
|
||||
|
||||
mEventReceived = true;
|
||||
mMsgCondition.signal();
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
virtual ScopedAStatus onSessionEvent(const vector<uint8_t>& sessionId, int32_t event,
|
||||
int32_t arg, const vector<uint8_t>& data) override {
|
||||
Mutex::Autolock autoLock(mMsgLock);
|
||||
mSessionId = sessionId;
|
||||
mEvent = event;
|
||||
mEventArg = arg;
|
||||
mEventData = data;
|
||||
|
||||
mEventReceived = true;
|
||||
mMsgCondition.signal();
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
virtual ScopedAStatus onStatusUpdate(StatusEvent event, int32_t arg) override {
|
||||
Mutex::Autolock autoLock(mMsgLock);
|
||||
mStatusEvent = event;
|
||||
mEventArg = arg;
|
||||
|
||||
mEventReceived = true;
|
||||
mMsgCondition.signal();
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
void testEventEcho(shared_ptr<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
|
||||
vector<uint8_t>& eventData);
|
||||
|
||||
void testSessionEventEcho(shared_ptr<ICas>& mediaCas, const vector<uint8_t>& sessionId,
|
||||
int32_t& event, int32_t& eventArg, vector<uint8_t>& eventData);
|
||||
|
||||
void testStatusUpdate(shared_ptr<ICas>& mediaCas, vector<uint8_t>* sessionId,
|
||||
SessionIntent intent, ScramblingMode mode);
|
||||
|
||||
private:
|
||||
int32_t mEvent = -1;
|
||||
int32_t mEventArg = -1;
|
||||
StatusEvent mStatusEvent;
|
||||
bool mEventReceived = false;
|
||||
vector<uint8_t> mEventData;
|
||||
vector<uint8_t> mSessionId;
|
||||
Mutex mMsgLock;
|
||||
android::Condition mMsgCondition;
|
||||
};
|
||||
|
||||
void MediaCasListener::testEventEcho(shared_ptr<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
|
||||
vector<uint8_t>& eventData) {
|
||||
mEventReceived = false;
|
||||
auto returnStatus = mediaCas->sendEvent(event, eventArg, eventData);
|
||||
EXPECT_TRUE(returnStatus.isOk());
|
||||
|
||||
Mutex::Autolock autoLock(mMsgLock);
|
||||
while (!mEventReceived) {
|
||||
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
|
||||
ADD_FAILURE() << "event not received within timeout";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(mEvent, event);
|
||||
EXPECT_EQ(mEventArg, eventArg);
|
||||
EXPECT_TRUE(mEventData == eventData);
|
||||
}
|
||||
|
||||
void MediaCasListener::testSessionEventEcho(shared_ptr<ICas>& mediaCas,
|
||||
const vector<uint8_t>& sessionId, int32_t& event,
|
||||
int32_t& eventArg, vector<uint8_t>& eventData) {
|
||||
mEventReceived = false;
|
||||
EXPECT_TRUE(mediaCas->sendSessionEvent(sessionId, event, eventArg, eventData).isOk());
|
||||
|
||||
Mutex::Autolock autoLock(mMsgLock);
|
||||
while (!mEventReceived) {
|
||||
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
|
||||
ADD_FAILURE() << "event not received within timeout";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(mSessionId == sessionId);
|
||||
EXPECT_EQ(mEvent, event);
|
||||
EXPECT_EQ(mEventArg, eventArg);
|
||||
EXPECT_TRUE(mEventData == eventData);
|
||||
}
|
||||
|
||||
void MediaCasListener::testStatusUpdate(shared_ptr<ICas>& mediaCas, vector<uint8_t>* sessionId,
|
||||
SessionIntent intent, ScramblingMode mode) {
|
||||
mEventReceived = false;
|
||||
EXPECT_TRUE(mediaCas->openSession(intent, mode, sessionId).isOk());
|
||||
|
||||
Mutex::Autolock autoLock(mMsgLock);
|
||||
while (!mEventReceived) {
|
||||
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
|
||||
ADD_FAILURE() << "event not received within timeout";
|
||||
return;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(mStatusEvent, static_cast<StatusEvent>(intent));
|
||||
EXPECT_EQ(mEventArg, static_cast<int32_t>(mode));
|
||||
}
|
||||
|
||||
class MediaCasAidlTest : public testing::TestWithParam<string> {
|
||||
public:
|
||||
virtual void SetUp() override {
|
||||
if (AServiceManager_isDeclared(GetParam().c_str())) {
|
||||
SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
|
||||
mService = IMediaCasService::fromBinder(binder);
|
||||
} else {
|
||||
mService = nullptr;
|
||||
}
|
||||
ASSERT_NE(mService, nullptr);
|
||||
}
|
||||
|
||||
shared_ptr<IMediaCasService> mService = nullptr;
|
||||
|
||||
protected:
|
||||
static void description(const string& description) {
|
||||
RecordProperty("description", description);
|
||||
}
|
||||
|
||||
shared_ptr<ICas> mMediaCas;
|
||||
shared_ptr<IDescrambler> mDescrambler;
|
||||
shared_ptr<MediaCasListener> mCasListener;
|
||||
typedef struct _OobInputTestParams {
|
||||
const SubSample* subSamples;
|
||||
int32_t numSubSamples;
|
||||
int64_t imemSizeActual;
|
||||
int64_t imemOffset;
|
||||
int64_t imemSize;
|
||||
int64_t srcOffset;
|
||||
int64_t dstOffset;
|
||||
} OobInputTestParams;
|
||||
|
||||
AssertionResult createCasPlugin(int32_t caSystemId);
|
||||
AssertionResult openCasSession(vector<uint8_t>* sessionId, SessionIntent intent,
|
||||
ScramblingMode mode);
|
||||
AssertionResult descrambleTestInputBuffer(const shared_ptr<IDescrambler>& descrambler,
|
||||
ScopedAStatus& descrambleStatus, uint8_t*& inMemory);
|
||||
AssertionResult descrambleTestOobInput(const shared_ptr<IDescrambler>& descrambler,
|
||||
ScopedAStatus& descrambleStatus,
|
||||
const OobInputTestParams& params);
|
||||
};
|
||||
|
||||
AssertionResult MediaCasAidlTest::createCasPlugin(int32_t caSystemId) {
|
||||
bool isSystemIdSupported;
|
||||
auto status = mService->isSystemIdSupported(caSystemId, &isSystemIdSupported);
|
||||
bool skipDescrambler = false;
|
||||
if (!status.isOk() || !isSystemIdSupported) {
|
||||
return AssertionFailure();
|
||||
}
|
||||
bool isDescramblerSupported;
|
||||
status = mService->isDescramblerSupported(caSystemId, &isDescramblerSupported);
|
||||
if (!status.isOk() || !isDescramblerSupported) {
|
||||
ALOGI("Skip Descrambler test since it's not required in cas.");
|
||||
mDescrambler = nullptr;
|
||||
skipDescrambler = true;
|
||||
}
|
||||
|
||||
mCasListener = SharedRefBase::make<MediaCasListener>();
|
||||
status = mService->createPlugin(caSystemId, mCasListener, &mMediaCas);
|
||||
if (!status.isOk()) {
|
||||
return AssertionFailure();
|
||||
}
|
||||
if (mMediaCas == nullptr) {
|
||||
return AssertionFailure();
|
||||
}
|
||||
|
||||
if (skipDescrambler) {
|
||||
return AssertionSuccess();
|
||||
}
|
||||
|
||||
status = mService->createDescrambler(caSystemId, &mDescrambler);
|
||||
if (!status.isOk()) {
|
||||
return AssertionFailure();
|
||||
}
|
||||
|
||||
return AssertionResult(mDescrambler != nullptr);
|
||||
}
|
||||
|
||||
AssertionResult MediaCasAidlTest::openCasSession(vector<uint8_t>* sessionId, SessionIntent intent,
|
||||
ScramblingMode mode) {
|
||||
return AssertionResult(mMediaCas->openSession(intent, mode, sessionId).isOk());
|
||||
}
|
||||
|
||||
AssertionResult MediaCasAidlTest::descrambleTestInputBuffer(
|
||||
const shared_ptr<IDescrambler>& descrambler, ScopedAStatus& descrambleStatus,
|
||||
uint8_t*& sharedMemory) {
|
||||
vector<SubSample> subSample(kSubSamples,
|
||||
kSubSamples + (sizeof(kSubSamples) / sizeof(SubSample)));
|
||||
|
||||
int size = sizeof(kInBinaryBuffer);
|
||||
auto fd = ashmem_create_region("vts-cas", size);
|
||||
if (fd < 0) {
|
||||
ALOGE("ashmem_create_region failed");
|
||||
return AssertionFailure();
|
||||
}
|
||||
|
||||
sharedMemory =
|
||||
static_cast<uint8_t*>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
|
||||
if (sharedMemory == reinterpret_cast<uint8_t*>(MAP_FAILED)) {
|
||||
ALOGE("mmap failed");
|
||||
return AssertionFailure();
|
||||
}
|
||||
|
||||
memcpy(sharedMemory, kInBinaryBuffer, size);
|
||||
|
||||
auto dupFd = dup(fd);
|
||||
|
||||
SharedBuffer srcBuffer = {.heapBase.fd = ScopedFileDescriptor(std::move(fd)),
|
||||
.heapBase.size = size,
|
||||
.offset = 0,
|
||||
.size = size};
|
||||
|
||||
SharedBuffer dupBuffer = {.heapBase.fd = ScopedFileDescriptor(dupFd),
|
||||
.heapBase.size = size,
|
||||
.offset = 0,
|
||||
.size = size};
|
||||
|
||||
DestinationBuffer dstBuffer;
|
||||
dstBuffer.set<DestinationBuffer::nonsecureMemory>(std::move(dupBuffer));
|
||||
|
||||
int32_t outBytes;
|
||||
descrambleStatus = descrambler->descramble(ScramblingControl::EVENKEY /*2*/, subSample,
|
||||
srcBuffer, 0, dstBuffer, 0, &outBytes);
|
||||
if (!descrambleStatus.isOk()) {
|
||||
ALOGI("descramble failed, status=%d, outBytes=%u, error=%s", descrambleStatus.getStatus(),
|
||||
outBytes, descrambleStatus.getDescription().c_str());
|
||||
}
|
||||
return AssertionResult(descrambleStatus.isOk());
|
||||
}
|
||||
|
||||
AssertionResult MediaCasAidlTest::descrambleTestOobInput(
|
||||
const shared_ptr<IDescrambler>& descrambler, ScopedAStatus& descrambleStatus,
|
||||
const OobInputTestParams& params) {
|
||||
vector<SubSample> subSample(params.subSamples, params.subSamples + params.numSubSamples);
|
||||
|
||||
auto fd = ashmem_create_region("vts-cas", params.imemSizeActual);
|
||||
if (fd < 0) {
|
||||
ALOGE("ashmem_create_region failed");
|
||||
return AssertionFailure();
|
||||
}
|
||||
|
||||
auto dupFd = dup(fd);
|
||||
|
||||
SharedBuffer srcBuffer = {.heapBase.fd = ScopedFileDescriptor(std::move(fd)),
|
||||
.heapBase.size = params.imemSizeActual,
|
||||
.offset = params.imemOffset,
|
||||
.size = params.imemSize};
|
||||
|
||||
SharedBuffer dupBuffer = {.heapBase.fd = ScopedFileDescriptor(dupFd),
|
||||
.heapBase.size = params.imemSizeActual,
|
||||
.offset = params.imemOffset,
|
||||
.size = params.imemSize};
|
||||
|
||||
DestinationBuffer dstBuffer;
|
||||
dstBuffer.set<DestinationBuffer::nonsecureMemory>(std::move(dupBuffer));
|
||||
|
||||
int32_t outBytes;
|
||||
descrambleStatus =
|
||||
descrambler->descramble(ScramblingControl::EVENKEY /*2*/, subSample, srcBuffer,
|
||||
params.srcOffset, dstBuffer, params.dstOffset, &outBytes);
|
||||
if (!descrambleStatus.isOk()) {
|
||||
ALOGI("descramble failed, status=%d, outBytes=%u, error=%s", descrambleStatus.getStatus(),
|
||||
outBytes, descrambleStatus.getDescription().c_str());
|
||||
}
|
||||
return AssertionResult(descrambleStatus.isOk());
|
||||
}
|
||||
|
||||
TEST_P(MediaCasAidlTest, EnumeratePlugins) {
|
||||
description("Test enumerate plugins");
|
||||
|
||||
vector<AidlCasPluginDescriptor> descriptors;
|
||||
EXPECT_TRUE(mService->enumeratePlugins(&descriptors).isOk());
|
||||
|
||||
if (descriptors.size() == 0) {
|
||||
ALOGW("[ WARN ] enumeratePlugins list empty");
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < descriptors.size(); i++) {
|
||||
int32_t caSystemId = descriptors[i].caSystemId;
|
||||
|
||||
ASSERT_TRUE(createCasPlugin(caSystemId));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MediaCasAidlTest, TestInvalidSystemIdFails) {
|
||||
description("Test failure for invalid system ID");
|
||||
|
||||
bool isSystemIdSupported;
|
||||
auto status = mService->isSystemIdSupported(INVALID_SYSTEM_ID, &isSystemIdSupported);
|
||||
|
||||
EXPECT_TRUE(status.isOk());
|
||||
ASSERT_FALSE(isSystemIdSupported);
|
||||
|
||||
bool isDescramblerSupported;
|
||||
status = mService->isDescramblerSupported(INVALID_SYSTEM_ID, &isDescramblerSupported);
|
||||
|
||||
EXPECT_TRUE(status.isOk());
|
||||
ASSERT_FALSE(isDescramblerSupported);
|
||||
|
||||
shared_ptr<ICas> mediaCas;
|
||||
shared_ptr<MediaCasListener> casListener = SharedRefBase::make<MediaCasListener>();
|
||||
status = mService->createPlugin(INVALID_SYSTEM_ID, casListener, &mediaCas);
|
||||
ASSERT_TRUE(status.isOk());
|
||||
EXPECT_EQ(mediaCas, nullptr);
|
||||
|
||||
shared_ptr<IDescrambler> descrambler;
|
||||
status = mService->createDescrambler(INVALID_SYSTEM_ID, &descrambler);
|
||||
ASSERT_TRUE(status.isOk());
|
||||
EXPECT_EQ(descrambler, nullptr);
|
||||
}
|
||||
|
||||
TEST_P(MediaCasAidlTest, TestClearKeyPluginInstalled) {
|
||||
description("Test if ClearKey plugin is installed");
|
||||
|
||||
vector<AidlCasPluginDescriptor> descriptors;
|
||||
EXPECT_TRUE(mService->enumeratePlugins(&descriptors).isOk());
|
||||
|
||||
if (descriptors.size() == 0) {
|
||||
ALOGW("[ WARN ] enumeratePlugins list empty");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < descriptors.size(); i++) {
|
||||
int32_t caSystemId = descriptors[i].caSystemId;
|
||||
if (CLEAR_KEY_SYSTEM_ID == caSystemId) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ADD_FAILURE() << "ClearKey plugin not installed";
|
||||
}
|
||||
|
||||
TEST_P(MediaCasAidlTest, TestClearKeySessionClosedAfterRelease) {
|
||||
description("Test that all sessions are closed after a MediaCas object is released");
|
||||
|
||||
ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
|
||||
|
||||
EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
|
||||
|
||||
SessionIntent intent = SessionIntent::LIVE;
|
||||
ScramblingMode mode = ScramblingMode::DVB_CSA1;
|
||||
|
||||
vector<uint8_t> sessionId;
|
||||
ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
|
||||
|
||||
vector<uint8_t> streamSessionId;
|
||||
ASSERT_TRUE(openCasSession(&streamSessionId, intent, mode));
|
||||
|
||||
EXPECT_TRUE(mMediaCas->release().isOk());
|
||||
|
||||
if (mDescrambler != nullptr) {
|
||||
auto status = mDescrambler->setMediaCasSession(sessionId);
|
||||
EXPECT_FALSE(status.isOk());
|
||||
EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, status.getServiceSpecificError());
|
||||
|
||||
status = mDescrambler->setMediaCasSession(streamSessionId);
|
||||
EXPECT_FALSE(status.isOk());
|
||||
EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, status.getServiceSpecificError());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MediaCasAidlTest, TestClearKeyErrors) {
|
||||
description("Test that invalid call sequences fail with expected error codes");
|
||||
|
||||
ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
|
||||
|
||||
/*
|
||||
* Test MediaCas error codes
|
||||
*/
|
||||
// Provision should fail with an invalid asset string
|
||||
auto returnStatus = mMediaCas->provision("invalid asset string");
|
||||
EXPECT_FALSE(returnStatus.isOk());
|
||||
EXPECT_EQ(Status::ERROR_CAS_NO_LICENSE, returnStatus.getServiceSpecificError());
|
||||
|
||||
SessionIntent intent = SessionIntent::LIVE;
|
||||
ScramblingMode mode = ScramblingMode::DVB_CSA1;
|
||||
|
||||
// Open a session, then close it so that it should become invalid
|
||||
vector<uint8_t> invalidSessionId;
|
||||
ASSERT_TRUE(openCasSession(&invalidSessionId, intent, mode));
|
||||
EXPECT_TRUE(mMediaCas->closeSession(invalidSessionId).isOk());
|
||||
|
||||
// processEcm should fail with an invalid session id
|
||||
vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
|
||||
returnStatus = mMediaCas->processEcm(invalidSessionId, ecm);
|
||||
EXPECT_FALSE(returnStatus.isOk());
|
||||
EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus.getServiceSpecificError());
|
||||
|
||||
vector<uint8_t> sessionId;
|
||||
ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
|
||||
|
||||
// processEcm should fail without provisioning
|
||||
returnStatus = mMediaCas->processEcm(sessionId, ecm);
|
||||
EXPECT_FALSE(returnStatus.isOk());
|
||||
EXPECT_EQ(Status::ERROR_CAS_NOT_PROVISIONED, returnStatus.getServiceSpecificError());
|
||||
|
||||
EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
|
||||
|
||||
// processEcm should fail with ecm with bad descriptor count
|
||||
ecm[17] = 0x03; // change the descriptor count field to 3 (invalid)
|
||||
returnStatus = mMediaCas->processEcm(sessionId, ecm);
|
||||
EXPECT_FALSE(returnStatus.isOk());
|
||||
EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus.getServiceSpecificError());
|
||||
|
||||
// processEcm should fail with ecm buffer that's too short
|
||||
ecm.resize(8);
|
||||
returnStatus = mMediaCas->processEcm(sessionId, ecm);
|
||||
EXPECT_FALSE(returnStatus.isOk());
|
||||
EXPECT_EQ(Status::BAD_VALUE, returnStatus.getServiceSpecificError());
|
||||
|
||||
if (mDescrambler != nullptr) {
|
||||
/*
|
||||
* Test MediaDescrambler error codes
|
||||
*/
|
||||
// setMediaCasSession should fail with an invalid session id
|
||||
returnStatus = mDescrambler->setMediaCasSession(invalidSessionId);
|
||||
EXPECT_FALSE(returnStatus.isOk());
|
||||
EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus.getServiceSpecificError());
|
||||
|
||||
// descramble should fail without a valid session
|
||||
ScopedAStatus descrambleStatus = ScopedAStatus::ok();
|
||||
uint8_t* sharedBuffer = nullptr;
|
||||
|
||||
ASSERT_FALSE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
|
||||
EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED,
|
||||
descrambleStatus.getServiceSpecificError());
|
||||
|
||||
// Now set a valid session, should still fail because no valid ecm is processed
|
||||
EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
|
||||
ASSERT_FALSE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
|
||||
EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus.getServiceSpecificError());
|
||||
|
||||
// Verify that requiresSecureDecoderComponent handles empty mime
|
||||
bool requiresSecureDecoderComponent = true;
|
||||
EXPECT_TRUE(
|
||||
mDescrambler->requiresSecureDecoderComponent("", &requiresSecureDecoderComponent)
|
||||
.isOk());
|
||||
EXPECT_FALSE(requiresSecureDecoderComponent);
|
||||
|
||||
// Verify that requiresSecureDecoderComponent handles invalid mime
|
||||
requiresSecureDecoderComponent = true;
|
||||
EXPECT_TRUE(
|
||||
mDescrambler->requiresSecureDecoderComponent("bad", &requiresSecureDecoderComponent)
|
||||
.isOk());
|
||||
EXPECT_FALSE(requiresSecureDecoderComponent);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MediaCasAidlTest, TestClearKeyApisWithSession) {
|
||||
description("Test that valid call sequences with SessionEvent send and receive");
|
||||
|
||||
ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
|
||||
|
||||
EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
|
||||
|
||||
vector<uint8_t> pvtData;
|
||||
pvtData.resize(256);
|
||||
EXPECT_TRUE(mMediaCas->setPrivateData(pvtData).isOk());
|
||||
|
||||
SessionIntent intent = SessionIntent::LIVE;
|
||||
ScramblingMode mode = ScramblingMode::DVB_CSA1;
|
||||
|
||||
vector<uint8_t> sessionId;
|
||||
ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
|
||||
EXPECT_TRUE(mMediaCas->setSessionPrivateData(sessionId, pvtData).isOk());
|
||||
|
||||
vector<uint8_t> streamSessionId;
|
||||
ASSERT_TRUE(openCasSession(&streamSessionId, intent, mode));
|
||||
EXPECT_TRUE(mMediaCas->setSessionPrivateData(streamSessionId, pvtData).isOk());
|
||||
|
||||
if (mDescrambler != nullptr) {
|
||||
EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
|
||||
EXPECT_TRUE(mDescrambler->setMediaCasSession(streamSessionId).isOk());
|
||||
}
|
||||
|
||||
vector<uint8_t> nullPtrVector(0);
|
||||
EXPECT_TRUE(mMediaCas->refreshEntitlements(3, nullPtrVector).isOk());
|
||||
|
||||
vector<uint8_t> refreshData{0, 1, 2, 3};
|
||||
EXPECT_TRUE(mMediaCas->refreshEntitlements(10, refreshData).isOk());
|
||||
|
||||
int32_t eventID = 1;
|
||||
int32_t eventArg = 2;
|
||||
mCasListener->testEventEcho(mMediaCas, eventID, eventArg, nullPtrVector);
|
||||
mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, nullPtrVector);
|
||||
|
||||
eventID = 3;
|
||||
eventArg = 4;
|
||||
vector<uint8_t> eventData{'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'};
|
||||
mCasListener->testEventEcho(mMediaCas, eventID, eventArg, eventData);
|
||||
mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, eventData);
|
||||
|
||||
mCasListener->testStatusUpdate(mMediaCas, &sessionId, intent, mode);
|
||||
|
||||
vector<uint8_t> clearKeyEmmData{'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'};
|
||||
EXPECT_TRUE(mMediaCas->processEmm(clearKeyEmmData).isOk());
|
||||
|
||||
vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
|
||||
EXPECT_TRUE(mMediaCas->processEcm(sessionId, ecm).isOk());
|
||||
EXPECT_TRUE(mMediaCas->processEcm(streamSessionId, ecm).isOk());
|
||||
|
||||
if (mDescrambler != nullptr) {
|
||||
bool requiresSecureDecoderComponent = true;
|
||||
EXPECT_TRUE(mDescrambler
|
||||
->requiresSecureDecoderComponent("video/avc",
|
||||
&requiresSecureDecoderComponent)
|
||||
.isOk());
|
||||
EXPECT_FALSE(requiresSecureDecoderComponent);
|
||||
|
||||
ScopedAStatus descrambleStatus = ScopedAStatus::ok();
|
||||
uint8_t* sharedBuffer = nullptr;
|
||||
|
||||
ASSERT_TRUE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
|
||||
|
||||
int compareResult =
|
||||
memcmp(static_cast<const void*>(sharedBuffer),
|
||||
static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
|
||||
EXPECT_EQ(0, compareResult);
|
||||
|
||||
EXPECT_TRUE(mDescrambler->release().isOk());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(mMediaCas->release().isOk());
|
||||
}
|
||||
|
||||
TEST_P(MediaCasAidlTest, TestClearKeyOobFails) {
|
||||
description("Test that oob descramble request fails with expected error");
|
||||
|
||||
ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
|
||||
EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
|
||||
|
||||
SessionIntent intent = SessionIntent::LIVE;
|
||||
ScramblingMode mode = ScramblingMode::DVB_CSA1;
|
||||
|
||||
vector<uint8_t> sessionId;
|
||||
ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
|
||||
|
||||
if (mDescrambler != nullptr) {
|
||||
EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
|
||||
}
|
||||
|
||||
vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
|
||||
EXPECT_TRUE(mMediaCas->processEcm(sessionId, ecm).isOk());
|
||||
|
||||
if (mDescrambler != nullptr) {
|
||||
ScopedAStatus descrambleStatus = ScopedAStatus::ok();
|
||||
|
||||
// test invalid src buffer offset
|
||||
ASSERT_FALSE(
|
||||
descrambleTestOobInput(mDescrambler, descrambleStatus,
|
||||
{.subSamples = kSubSamples,
|
||||
.numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
|
||||
.imemSizeActual = sizeof(kInBinaryBuffer),
|
||||
.imemOffset = 0xcccccc,
|
||||
.imemSize = sizeof(kInBinaryBuffer),
|
||||
.srcOffset = 0,
|
||||
.dstOffset = 0}));
|
||||
EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
|
||||
|
||||
// test invalid src buffer size
|
||||
ASSERT_FALSE(
|
||||
descrambleTestOobInput(mDescrambler, descrambleStatus,
|
||||
{.subSamples = kSubSamples,
|
||||
.numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
|
||||
.imemSizeActual = sizeof(kInBinaryBuffer),
|
||||
.imemOffset = 0,
|
||||
.imemSize = 0xcccccc,
|
||||
.srcOffset = 0,
|
||||
.dstOffset = 0}));
|
||||
EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
|
||||
|
||||
// test invalid src buffer size
|
||||
ASSERT_FALSE(
|
||||
descrambleTestOobInput(mDescrambler, descrambleStatus,
|
||||
{.subSamples = kSubSamples,
|
||||
.numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
|
||||
.imemSizeActual = sizeof(kInBinaryBuffer),
|
||||
.imemOffset = 1,
|
||||
.imemSize = -1,
|
||||
.srcOffset = 0,
|
||||
.dstOffset = 0}));
|
||||
EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
|
||||
|
||||
// test invalid srcOffset
|
||||
ASSERT_FALSE(
|
||||
descrambleTestOobInput(mDescrambler, descrambleStatus,
|
||||
{.subSamples = kSubSamples,
|
||||
.numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
|
||||
.imemSizeActual = sizeof(kInBinaryBuffer),
|
||||
.imemOffset = 0,
|
||||
.imemSize = sizeof(kInBinaryBuffer),
|
||||
.srcOffset = 0xcccccc,
|
||||
.dstOffset = 0}));
|
||||
EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
|
||||
|
||||
// test invalid dstOffset
|
||||
ASSERT_FALSE(
|
||||
descrambleTestOobInput(mDescrambler, descrambleStatus,
|
||||
{.subSamples = kSubSamples,
|
||||
.numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
|
||||
.imemSizeActual = sizeof(kInBinaryBuffer),
|
||||
.imemOffset = 0,
|
||||
.imemSize = sizeof(kInBinaryBuffer),
|
||||
.srcOffset = 0,
|
||||
.dstOffset = 0xcccccc}));
|
||||
EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
|
||||
|
||||
// test detection of oob subsample sizes
|
||||
const SubSample invalidSubSamples1[] = {{162, 0}, {0, 184}, {0, 0xdddddd}};
|
||||
|
||||
ASSERT_FALSE(descrambleTestOobInput(
|
||||
mDescrambler, descrambleStatus,
|
||||
{.subSamples = invalidSubSamples1,
|
||||
.numSubSamples = sizeof(invalidSubSamples1) / sizeof(SubSample),
|
||||
.imemSizeActual = sizeof(kInBinaryBuffer),
|
||||
.imemOffset = 0,
|
||||
.imemSize = sizeof(kInBinaryBuffer),
|
||||
.srcOffset = 0,
|
||||
.dstOffset = 0}));
|
||||
EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
|
||||
|
||||
// test detection of overflowing subsample sizes
|
||||
const SubSample invalidSubSamples2[] = {{162, 0}, {0, 184}, {2, -1}};
|
||||
|
||||
ASSERT_FALSE(descrambleTestOobInput(
|
||||
mDescrambler, descrambleStatus,
|
||||
{.subSamples = invalidSubSamples2,
|
||||
.numSubSamples = sizeof(invalidSubSamples2) / sizeof(SubSample),
|
||||
.imemSizeActual = sizeof(kInBinaryBuffer),
|
||||
.imemOffset = 0,
|
||||
.imemSize = sizeof(kInBinaryBuffer),
|
||||
.srcOffset = 0,
|
||||
.dstOffset = 0}));
|
||||
EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
|
||||
|
||||
EXPECT_TRUE(mDescrambler->release().isOk());
|
||||
}
|
||||
EXPECT_TRUE(mMediaCas->release().isOk());
|
||||
}
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MediaCasAidlTest);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
PerInstance, MediaCasAidlTest,
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(IMediaCasService::descriptor)),
|
||||
android::PrintInstanceNameToString);
|
||||
|
||||
// Start thread pool to receive callbacks from AIDL service.
|
||||
int main(int argc, char** argv) {
|
||||
InitGoogleTest(&argc, argv);
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(1);
|
||||
ABinderProcess_startThreadPool();
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -199,6 +199,13 @@
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
<hal format="aidl" optional="true">
|
||||
<name>android.hardware.cas</name>
|
||||
<interface>
|
||||
<name>IMediaCasService</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
<hal format="aidl" optional="true">
|
||||
<name>android.hardware.confirmationui</name>
|
||||
<version>1</version>
|
||||
|
||||
Reference in New Issue
Block a user