// 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;

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

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

/// 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(bytes certificate) -> () 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(LicenseSessionType session_type,
                         request<LicenseSession> license_session)
        -> (SessionId session_id);

    /// 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(SessionId session_id,
                       request<LicenseSession> license_session);

    /// 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(DecryptorParams params,
                    request<fuchsia.media.StreamProcessor> decryptor);

    /// 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(HdcpVersion hdcp_version) -> (KeyStatus key_status);

    /// 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() -> (vector<EncryptionScheme>:MAX encryption_schemes);
};
