// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.media.drm;

using fuchsia.media;

type DecryptorParams = table {
    /// Requires the decryptor [`fuchsia.media/StreamProcessor`] to only output
    /// to secure buffers.
    1: require_secure_mode bool;

    /// Initial format details for the [`fuchsia.media/StreamProcessor`].
    2: input_details fuchsia.media.FormatDetails;
};

/// A protocol for managing content license sessions and providing decryption of
/// media content. There may be zero to many active [`LicenseSession`]s
/// associated with a `ContentDecryptionModule`, each with their own sets of
/// keys.
///
/// From an EME client's perspective, this protocol has a 1:1 relationship with
/// the MediaKeys object.
protocol ContentDecryptionModule {
    /// Indicates that the `ContentDecryptionModule` is provisioned.
    ///
    /// In order to create `LicenseSession`s, a `ContentDecryptionModule` must
    /// be provisioned. A `ContentDecryptionModule` is not considered
    /// provisioned until it meets the requirements for the underlying DRM
    /// system. The DRM system may not require provisioning, may only require
    /// factory provisioning or may require both factory provisioning and
    /// service instance provisioning.
    ///
    /// If the `ContentDecryptionModule` has already has sufficient
    /// provisioning, this event will be sent immediately upon creation. If the
    /// `ContentDecryptionModule` has its provisioning removed, then the server
    /// will close the channel and also close any active `LicenseSession`s or
    /// Decryptors.
    ///
    /// If the DRM system does not require provisioning at all, this
    /// event should still be sent to notify the client that it can create
    /// `LicenseSession`s.
    -> OnProvisioned();

    /// Sets the certificate to be used for encrypting outgoing messages.
    ///
    /// + request `certificate` a buffer containing the certificate to be used.
    /// * error an [`Error`] indicating the reason for failure.
    SetServerCertificate(struct {
        certificate vector<uint8>:MAX;
    }) -> (struct {}) error Error;

    /// Creates a new session for the given type.
    ///
    /// The `session_id` will be generated by the [`ContentDecryptionModule`]
    /// and can be used to reload the session after closing. If the
    /// `session_type` is not supported by the underlying DRM system, it will
    /// immediately close the `license_session`.
    ///
    /// + request `session_type` a field containing either
    ///   [`LicenseSessionType.TEMPORARY`] or
    ///   [`LicenseSessionType.PERSISTENT_LICENSE`]
    /// + request `license_session` the server endpoint of the
    ///   [`LicenseSession`]
    /// - response `session_id` an identifier that can be used to reload the
    ///   session later (if persistent).
    CreateLicenseSession(resource struct {
        session_type LicenseSessionType;
        license_session server_end:LicenseSession;
    }) -> (struct {
        session_id SessionId;
    });

    /// Loads an existing session from storage using the given `session_id`.
    ///
    /// If the session is not found, then the `license_session` will be closed.
    ///
    /// + request `session_id` contains an identifier of which session should be
    ///   loaded from storage.
    /// + request `license_session` the server endpoint of the
    ///   [`LicenseSession`].
    LoadLicenseSession(resource struct {
        session_id SessionId;
        license_session server_end:LicenseSession;
    });

    /// Creates a Decryptor [`fuchsia.media/StreamProcessor`] to be used to
    /// decrypt content.
    ///
    /// This `decryptor` would have access to the union of keys created by all
    /// the active sessions for this [`ContentDecryptionModule`].
    ///
    /// + request `params` the parameters with which to create the `decryptor`.
    /// + request `decryptor` the server endpoint of the
    ///   `fuchsia.media/StreamProcessor`.
    CreateDecryptor(resource struct {
        params DecryptorParams;
        decryptor server_end:fuchsia.media.StreamProcessor;
    });

    /// Queries the status of a hypothetical key associated with an HDCP policy.
    ///
    /// This aids clients in determining which content type to fetch prior to
    /// establishing a [`LicenseSession`]. For example, if the device would
    /// restrict output for HDCP 1.x, then the client can choose to fetch SD
    /// content rather than HD.
    ///
    /// + request `hdcp_version` a field containing the HDCP version to check,
    ///   such as "1.2" or "2.0".
    /// - response `key_status` a field indicating what the status of a
    ///   hypothetical key would be for this device if one could be licensed.
    GetKeyStatusForHdcpVersion(struct {
        hdcp_version HdcpVersion;
    }) -> (struct {
        key_status KeyStatus;
    });

    /// Queries for the list of supported encryption schemes.
    ///
    /// This returns a list of the supported encryption schemes that the
    /// `ContentDecryptionModule` supports, such as 'cenc' or 'cbcs'. If the
    /// implementation supports passing unencrypted frames through decryption
    /// prior to license arrival, it should also report
    /// `fuchsia.media.UNENCRYPTED` as a supported scheme.
    ///
    /// - response `encryption_schemes` a list of the supported encryption
    ///   schemes.
    GetSupportedEncryptionSchemes() -> (struct {
        encryption_schemes vector<EncryptionScheme>:MAX;
    });
};
