Reorganize drm hal modules

Previously the drm and crypto plugins were separate hals.
This implied a separation of implementation libraries which
causes problems for some drm schemes. The reorganization
combines the hals into a single interface under drm.

Tests: basic gtests passing

Change-Id: I5cde6ff9f60625a0219731c4dbfcaefbd9f27f88
related-to-bug: 32815560
diff --git a/drm/1.0/Android.bp b/drm/1.0/Android.bp
new file mode 100644
index 0000000..d899114
--- /dev/null
+++ b/drm/1.0/Android.bp
@@ -0,0 +1,88 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.drm@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.drm@1.0",
+    srcs: [
+        "types.hal",
+        "ICryptoFactory.hal",
+        "ICryptoPlugin.hal",
+        "IDrmFactory.hal",
+        "IDrmPlugin.hal",
+        "IDrmPluginListener.hal",
+    ],
+    out: [
+        "android/hardware/drm/1.0/types.cpp",
+        "android/hardware/drm/1.0/CryptoFactoryAll.cpp",
+        "android/hardware/drm/1.0/CryptoPluginAll.cpp",
+        "android/hardware/drm/1.0/DrmFactoryAll.cpp",
+        "android/hardware/drm/1.0/DrmPluginAll.cpp",
+        "android/hardware/drm/1.0/DrmPluginListenerAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.drm@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.drm@1.0",
+    srcs: [
+        "types.hal",
+        "ICryptoFactory.hal",
+        "ICryptoPlugin.hal",
+        "IDrmFactory.hal",
+        "IDrmPlugin.hal",
+        "IDrmPluginListener.hal",
+    ],
+    out: [
+        "android/hardware/drm/1.0/types.h",
+        "android/hardware/drm/1.0/ICryptoFactory.h",
+        "android/hardware/drm/1.0/IHwCryptoFactory.h",
+        "android/hardware/drm/1.0/BnHwCryptoFactory.h",
+        "android/hardware/drm/1.0/BpHwCryptoFactory.h",
+        "android/hardware/drm/1.0/BsCryptoFactory.h",
+        "android/hardware/drm/1.0/ICryptoPlugin.h",
+        "android/hardware/drm/1.0/IHwCryptoPlugin.h",
+        "android/hardware/drm/1.0/BnHwCryptoPlugin.h",
+        "android/hardware/drm/1.0/BpHwCryptoPlugin.h",
+        "android/hardware/drm/1.0/BsCryptoPlugin.h",
+        "android/hardware/drm/1.0/IDrmFactory.h",
+        "android/hardware/drm/1.0/IHwDrmFactory.h",
+        "android/hardware/drm/1.0/BnHwDrmFactory.h",
+        "android/hardware/drm/1.0/BpHwDrmFactory.h",
+        "android/hardware/drm/1.0/BsDrmFactory.h",
+        "android/hardware/drm/1.0/IDrmPlugin.h",
+        "android/hardware/drm/1.0/IHwDrmPlugin.h",
+        "android/hardware/drm/1.0/BnHwDrmPlugin.h",
+        "android/hardware/drm/1.0/BpHwDrmPlugin.h",
+        "android/hardware/drm/1.0/BsDrmPlugin.h",
+        "android/hardware/drm/1.0/IDrmPluginListener.h",
+        "android/hardware/drm/1.0/IHwDrmPluginListener.h",
+        "android/hardware/drm/1.0/BnHwDrmPluginListener.h",
+        "android/hardware/drm/1.0/BpHwDrmPluginListener.h",
+        "android/hardware/drm/1.0/BsDrmPluginListener.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.drm@1.0",
+    generated_sources: ["android.hardware.drm@1.0_genc++"],
+    generated_headers: ["android.hardware.drm@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.drm@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/drm/1.0/ICryptoFactory.hal b/drm/1.0/ICryptoFactory.hal
new file mode 100644
index 0000000..aeab9bc
--- /dev/null
+++ b/drm/1.0/ICryptoFactory.hal
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 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.drm@1.0;
+
+import ICryptoPlugin;
+
+/**
+ * Ref: frameworks/native/include/media/hardware/CryptoAPI.h:CryptoFactory
+ *
+ * ICryptoFactory is the main entry point for interacting with a vendor's
+ * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
+ * which are used by a codec to decrypt protected video content.
+ */
+interface ICryptoFactory {
+    /**
+     * Determine if a crypto scheme is supported by this HAL
+     *
+     * @param uuid identifies the crypto scheme in question
+     * @return isSupported must be true only if the scheme is supported
+     */
+    isCryptoSchemeSupported(uint8_t[16] uuid) generates(bool isSupported);
+
+    /**
+     * Create a crypto plugin for the specified uuid and scheme-specific
+     * initialization data.
+     *
+     * @param uuid uniquely identifies the drm scheme. See
+     * http://dashif.org/identifiers/protection for uuid assignments
+     * @param initData scheme-specific init data.
+     * @return status the status of the call. The HAL implementation must return
+     * OK if the plugin is created and ERROR_DRM_CANNOT_HANDLE if the plugin
+     * cannot be created.
+     * @return cryptoPlugin the created ICryptoPlugin
+     */
+    createPlugin(uint8_t[16] uuid, vec<uint8_t> initData)
+        generates (Status status, ICryptoPlugin cryptoPlugin);
+};
diff --git a/drm/1.0/ICryptoPlugin.hal b/drm/1.0/ICryptoPlugin.hal
new file mode 100644
index 0000000..d66151e
--- /dev/null
+++ b/drm/1.0/ICryptoPlugin.hal
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 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.drm@1.0;
+
+import android.hardware.drm@1.0::types;
+
+/**
+ * Ref: frameworks/native/include/media/hardware/CryptoAPI.h:CryptoPlugin
+ *
+ * ICryptoPlugin is the HAL for vendor-provided crypto plugins.
+ * It allows crypto sessions to be opened and operated on, to
+ * load crypto keys for a codec to decrypt protected video content.
+ */
+interface ICryptoPlugin {
+    /**
+     * Check if the specified mime-type requires a secure decoder
+     * component.
+     *
+     * @param mime The content mime-type
+     * @return secureRequired must be true only if a secure decoder is required
+     * for the specified mime-type
+     */
+    requiresSecureDecoderComponent(string mime)
+        generates(bool secureRequired);
+
+    /**
+     * Notify a plugin of the currently configured resolution
+     *
+     * @param width - the display resolutions's width
+     * @param height - the display resolution's height
+     */
+    notifyResolution(uint32_t width, uint32_t height);
+
+    /**
+     * Associate a mediadrm session with this crypto session
+     *
+     * @param sessionId the MediaDrm session ID to associate with this crypto
+     * session
+     * @return status the status of the call, status must be
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened, or
+     * ERROR_DRM_CANNOT_HANDLE if the operation is not supported by the drm
+     * scheme.
+     */
+    setMediaDrmSession(vec<uint8_t> sessionId) generates(Status status);
+
+    /**
+     * Set a shared memory base for subsequent decrypt operations. The buffer
+     * base is a hidl_memory which maps shared memory in the HAL module.
+     * After the shared buffer base is established, the decrypt() method
+     * receives SharedBuffer instances which specify the buffer address range
+     * for decrypt source and destination addresses.
+     */
+    setSharedBufferBase(memory base);
+
+    /**
+     * Decrypt an array of subsamples from the source memory buffer to the
+     * destination memory buffer.
+     *
+     * @param secure a flag to indicate if a secure decoder is being used. This
+     * enables the plugin to configure buffer modes to work consistently with
+     * a secure decoder.
+     * @param the keyId for the key that should be used to do the
+     * the decryption. The keyId refers to a key in the associated
+     * MediaDrm instance.
+     * @param iv the initialization vector to use
+     * @param mode the crypto mode to use
+     * @param pattern the crypto pattern to use
+     * @param subSamples a vector of subsamples indicating the number
+     * of clear and encrypted bytes to process. This allows the decrypt
+     * call to operate on a range of subsamples in a single call
+     * @param source the input buffer for the decryption
+     * @param offset the offset of the first byte of encrypted data from
+     * the base of the source buffer
+     * @param destination the output buffer for the decryption
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_NO_LICENSE if no license keys have been
+     * loaded, ERROR_DRM_LICENSE_EXPIRED if the license keys have expired,
+     * ERROR_DRM_RESOURCE_BUSY if the resources required to perform the
+     * decryption are not available, ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION
+     * if required output protections are not active,
+     * ERROR_DRM_SESSION_NOT_OPENED if the decrypt session is not opened, or
+     * ERROR_DRM_CANNOT_HANDLE in other failure cases.
+     * @return bytesWritten the number of bytes output from the decryption
+     * @return detailedError if the error is a vendor-specific error, the
+     * vendor's crypto HAL may provide a detailed error string to help
+     * describe the error.
+     */
+    decrypt(bool secure, uint8_t[16] keyId, uint8_t[16] iv, Mode mode,
+        Pattern pattern, vec<SubSample> subSamples,
+            SharedBuffer source, uint64_t offset, DestinationBuffer destination)
+        generates(Status status, uint32_t bytesWritten, string detailedError);
+};
diff --git a/drm/1.0/IDrmFactory.hal b/drm/1.0/IDrmFactory.hal
new file mode 100644
index 0000000..de53929
--- /dev/null
+++ b/drm/1.0/IDrmFactory.hal
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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.drm@1.0;
+
+import IDrmPlugin;
+
+/**
+ * Ref: frameworks/native/include/media/drm/DrmAPI.h:DrmFactory
+ *
+ * IDrmFactory is the main entry point for interacting with a vendor's
+ * drm HAL to create drm plugin instances. A drm plugin instance
+ * creates drm sessions which are used to obtain keys for a crypto
+ * session so it can decrypt* protected video content.
+ */
+
+interface IDrmFactory {
+    /**
+     * Determine if a crypto scheme is supported by this HAL
+     *
+     * @param uuid identifies the crypto scheme in question
+     * @return isSupported must be true only if the scheme is supported
+     */
+    isCryptoSchemeSupported(uint8_t[16] uuid) generates(bool isSupported);
+
+    /**
+     * Determine if the HAL factory is able to construct plugins that support a
+     * given media container format specified by mimeType
+     *
+     * @param mimeType identifies the mime type in question
+     * @return isSupported must be true only if the scheme is supported
+     */
+    isContentTypeSupported(string mimeType) generates(bool isSupported);
+
+    /**
+     * Create a drm plugin instance for the specified uuid and scheme-specific
+     * initialization data.
+     *
+     * @param uuid uniquely identifies the drm scheme. See
+     * http://dashif.org/identifiers/protection for uuid assignments
+     * @return status the status of the call. The HAL implementation must return
+     * OK if the plugin is created and ERROR_DRM_CANNOT_HANDLE if the plugin
+     * cannot be created.
+     */
+    createPlugin(uint8_t[16] uuid) generates (Status status,
+            IDrmPlugin drmPlugin);
+};
diff --git a/drm/1.0/IDrmPlugin.hal b/drm/1.0/IDrmPlugin.hal
new file mode 100644
index 0000000..5bae22d
--- /dev/null
+++ b/drm/1.0/IDrmPlugin.hal
@@ -0,0 +1,542 @@
+/**
+ * Copyright (C) 2016 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.drm@1.0;
+
+import IDrmPluginListener;
+
+/**
+ * Ref: frameworks/native/include/media/drm/DrmAPI.h:DrmPlugin
+ *
+ * IDrmPlugin is used to interact with a specific drm plugin that was
+ * created by IDrm::createPlugin. A drm plugin provides methods for
+ * obtaining drm keys that may be used by a codec to decrypt protected
+ * video content.
+ */
+interface IDrmPlugin {
+
+    /**
+     * Open a new session with the DrmPlugin object. A session ID is returned
+     * in the sessionId parameter.
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_NOT_PROVISIONED if the device requires
+     * provisioning before it can open a session, ERROR_DRM_RESOURCE_BUSY if
+     * there are insufficent resources available to open a session,
+     * ERROR_DRM_CANNOT_HANDLE, if openSession is not supported at the time of
+     * the call or ERROR_DRM_INVALID_STATE if the HAL is in a state where a
+     * session cannot be opened.
+     * @return sessionId the session ID for the newly opened session
+     */
+    openSession() generates (Status status, SessionId sessionId);
+
+    /**
+     * Close a session on the DrmPlugin object
+     *
+     * @param sessionId the session id the call applies to
+     * @return status the status of the call.  The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the session cannot be closed.
+     */
+    closeSession(SessionId sessionId) generates (Status status);
+
+    /**
+     * A key request/response exchange occurs between the app and a License
+     * Server to obtain the keys required to decrypt the content.
+     * getKeyRequest() is used to obtain an opaque key request blob that is
+     * delivered to the license server.
+     *
+     * @param scope may be a sessionId or a keySetId, depending on the
+     * specified keyType. When the keyType is OFFLINE or STREAMING,
+     * scope should be set to the sessionId the keys will be provided to.
+     * When the keyType is RELEASE, scope should be set to the keySetId
+     * of the keys being released.
+     * @param initData container-specific data, its meaning is interpreted
+     * based on the mime type provided in the mimeType parameter. It could
+     * contain, for example, the content ID, key ID or other data obtained
+     * from the content metadata that is required to generate the key request.
+     * initData may be empty when keyType is RELEASE.
+     * @param mimeType identifies the mime type of the content
+     * @param keyType specifies if the keys are to be used for streaming,
+     * offline or a release
+     * @param optionalParameters included in the key request message to
+     * allow a client application to provide additional message parameters to
+     * the server.
+     *
+     * @return status the status of the call.  The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, ERROR_DRM_NOT_PROVISIONED if the device requires provisioning
+     * before it can generate a key request, ERROR_DRM_CANNOT_HANDLE if
+     * getKeyRequest is not supported at the time of the call, BAD_VALUE if any
+     * parameters are invalid or ERROR_DRM_INVALID_STATE if the HAL is in a state
+     * where a key request cannot be generated.
+     * @return request if successful, the opaque key request blob is returned
+     * @return requestType indicates type information about the returned
+     * request. The type may be one of INITIAL, RENEWAL or RELEASE. An
+     * INITIAL request is the first key request for a license. RENEWAL is a
+     * subsequent key request used to refresh the keys in a license. RELEASE
+     * corresponds to a keyType of RELEASE, which indicates keys are being
+     * released.
+     * @return defaultUrl the URL that the request may be sent to, if
+     * provided by the drm HAL. The app may choose to override this
+     * URL.
+     */
+    getKeyRequest(vec<uint8_t> scope, vec<uint8_t> initData,
+            string mimeType, KeyType keyType, KeyedVector optionalParameters)
+        generates (Status status, vec<uint8_t> request,
+                KeyRequestType requestType, string defaultUrl);
+
+    /**
+     * After a key response is received by the app, it is provided to the
+     * Drm plugin using provideKeyResponse.
+     *
+     * @param scope may be a sessionId or a keySetId depending on the type
+     * of the response. Scope should be set to the sessionId when the response
+     * is for either streaming or offline key requests. Scope should be set to
+     * the keySetId when the response is for a release request.
+     * @param response the response from the key server that is being
+     * provided to the drm HAL.
+     *
+     * @return status the status of the call.  The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, ERROR_DRM_NOT_PROVISIONED if the device requires provisioning
+     * before it can handle the key response, ERROR_DRM_DEVICE_REVOKED if the
+     * device has been disabled by the license policy, ERROR_DRM_CANNOT_HANDLE
+     * if provideKeyResponse is not supported at the time of the call, BAD_VALUE
+     * if any parameters are invalid or ERROR_DRM_INVALID_STATE if the HAL is
+     * in a state where a key response cannot be handled.
+     * @return keySetId when the response is for an offline key request, a
+     * keySetId is returned in the keySetId vector parameter that can be used
+     * to later restore the keys to a new session with the method restoreKeys.
+     * When the response is for a streaming or release request, no keySetId is
+     * returned.
+     */
+    provideKeyResponse(vec<uint8_t> scope, vec<uint8_t> response)
+        generates (Status status, vec<uint8_t> keySetId);
+
+    /**
+     * Remove the current keys from a session
+     *
+     * @param sessionId the session id the call applies to
+     * @return status the status of the call.  The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the keys cannot be removed.
+     */
+    removeKeys(SessionId sessionId) generates (Status status);
+
+    /**
+     * Restore persisted offline keys into a new session
+     *
+     * @param sessionId the session id the call applies to
+     * @param keySetId identifies the keys to load, obtained from a prior
+     * call to provideKeyResponse().
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where keys cannot be restored.
+     */
+    restoreKeys(SessionId sessionId,
+            vec<uint8_t> keySetId) generates (Status status);
+
+    /**
+     * Request an informative description of the license for the session. The
+     * status is in the form of {name, value} pairs. Since DRM license policies
+     * vary by vendor, the specific status field names are determined by each
+     * DRM vendor. Refer to your DRM provider documentation for definitions of
+     * the field names for a particular drm scheme.
+     *
+     * @param sessionId the session id the call applies to
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where key status cannot be queried.
+     * @return infoList a list of name value pairs describing the license
+     */
+    queryKeyStatus(SessionId sessionId)
+        generates (Status status, KeyedVector infoList);
+
+    /**
+     * A provision request/response exchange occurs between the app and a
+     * provisioning server to retrieve a device certificate. getProvisionRequest
+     * is used to obtain an opaque provisioning request blob that is delivered
+     * to the provisioning server.
+     *
+     * @param certificateType the type of certificate requested, e.g. "X.509"
+     * @param certificateAuthority identifies the certificate authority. A
+     * certificate authority (CA) is an entity which issues digital certificates
+     * for use by other parties. It is an example of a trusted third party.
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the sessionId is invalid or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the provision
+     * request cannot be generated.
+     * @return request if successful the opaque certificate request blob
+     * is returned
+     * @return defaultUrl URL that the provisioning request should be
+     * sent to, if known by the HAL implementation.  If the HAL implementation
+     * does not provide a defaultUrl, the returned string must be empty.
+     */
+    getProvisionRequest(string certificateType, string certificateAuthority)
+        generates (Status status, vec<uint8_t> request, string defaultUrl);
+
+    /**
+     * After a provision response is received by the app from a provisioning
+     * server, it is provided to the Drm HAL using provideProvisionResponse.
+     * The HAL implementation must receive the provision request and
+     * store the provisioned credentials.
+     *
+     * @param response the opaque provisioning response received by the
+     * app from a provisioning server.
+
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_DEVICE_REVOKED if the device has been
+     * disabled by the license policy, BAD_VALUE if any parameters are invalid
+     * or ERROR_DRM_INVALID_STATE if the HAL is in a state where the provision
+     * response cannot be handled.
+     * @return certificate the public certificate resulting from the provisioning
+     * operation, if any. An empty vector indicates that no certificate was
+     * returned.
+     * @return wrappedKey an opaque object containing encrypted private key
+     * material to be used by signRSA when computing an RSA signature on a
+     * message, see the signRSA method.
+     */
+    provideProvisionResponse(vec<uint8_t> response) generates (Status status,
+            vec<uint8_t> certificate, vec<uint8_t> wrappedKey);
+
+    /**
+     * SecureStop is a way of enforcing the concurrent stream limit per
+     * subscriber. It can securely monitor the lifetime of sessions across
+     * device reboots by periodically persisting the session lifetime
+     * status in secure storage.
+     *
+     * A signed version of the sessionID is written to persistent storage on the
+     * device when each MediaCrypto object is created and periodically during
+     * playback. The sessionID is signed by the device private key to prevent
+     * tampering.
+     *
+     * When playback is completed the session is destroyed, and the secure
+     * stops are queried by the app. The app then delivers the secure stop
+     * message to a server which verifies the signature to confirm that the
+     * session and its keys have been removed from the device. The persisted
+     * record on the device is removed after receiving and verifying the
+     * signed response from the server.
+     */
+
+    /**
+     * Get all secure stops on the device
+     *
+     * @return status the status of the call. The status must be OK or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stops
+     * cannot be returned.
+     * @return secureStops a list of the secure stop opaque objects
+     */
+    getSecureStops() generates
+        (Status status, vec<SecureStop> secureStops);
+
+    /**
+     * Get all secure stops by secure stop ID
+     *
+     * @param secureStopId the ID of the secure stop to return. The
+     * secure stop ID is delivered by the key server as part of the key
+     * response and must also be known by the app.
+     *
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the secureStopId is invalid or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stop
+     * cannot be returned.
+     * @return secureStop the secure stop opaque object
+     */
+
+    getSecureStop(SecureStopId secureStopId)
+        generates (Status status, SecureStop secureStop);
+
+    /**
+     * Release all secure stops on the device
+     *
+     * @return status the status of the call. The status must be OK or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure
+     * stops cannot be released.
+     */
+    releaseAllSecureStops() generates (Status status);
+
+    /**
+     * Release a secure stop by secure stop ID
+     *
+     * @param secureStopId the ID of the secure stop to release. The
+     * secure stop ID is delivered by the key server as part of the key
+     * response and must also be known by the app.
+     *
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the secureStopId is invalid or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stop
+     * cannot be released.
+     */
+    releaseSecureStop(vec<uint8_t> secureStopId) generates (Status status);
+
+    /**
+     * A drm scheme can have properties that are settable and readable
+     * by an app. There are a few forms of property access methods,
+     * depending on the data type of the property.
+     *
+     * Property values defined by the public API are:
+     *   "vendor" [string] identifies the maker of the drm scheme
+     *   "version" [string] identifies the version of the drm scheme
+     *   "description" [string] describes the drm scheme
+     *   'deviceUniqueId' [byte array] The device unique identifier is
+     *   established during device provisioning and provides a means of
+     *   uniquely identifying each device.
+     *
+     * Since drm scheme properties may vary, additional field names may be
+     * defined by each DRM vendor. Refer to your DRM provider documentation
+     * for definitions of its additional field names.
+     */
+
+    /**
+     * Read a string property value given the property name.
+     *
+     * @param propertyName the name of the property
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the property name is invalid,
+     * ERROR_DRM_CANNOT_HANDLE if the property is not supported, or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the property
+     * cannot be obtained.
+     * @return value the property value string
+     */
+    getPropertyString(string propertyName)
+        generates (Status status, string value);
+
+    /**
+     * Read a byte array property value given the property name.
+     *
+     * @param propertyName the name of the property
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the property name is invalid,
+     * ERROR_DRM_CANNOT_HANDLE if the property is not supported, or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the property
+     * cannot be obtained.
+     * @return value the property value byte array
+     */
+    getPropertyByteArray(string propertyName)
+        generates (Status status, vec<uint8_t> value);
+
+    /**
+     * Write a property string value given the property name
+     *
+     * @param propertyName the name of the property
+     * @param value the value to write
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the property name is invalid,
+     * ERROR_DRM_CANNOT_HANDLE if the property is not supported, or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the property
+     * cannot be set.
+     */
+    setPropertyString(string propertyName, string value)
+        generates (Status status);
+
+    /**
+     * Write a property byte array value given the property name
+     *
+     * @param propertyName the name of the property
+     * @param value the value to write
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the property name is invalid,
+     * ERROR_DRM_CANNOT_HANDLE if the property is not supported, or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the property
+     * cannot be set.
+     */
+    setPropertyByteArray(string propertyName, vec<uint8_t> value )
+        generates (Status status);
+
+    /**
+     * The following methods implement operations on a CryptoSession to support
+     * encrypt, decrypt, sign verify operations on operator-provided
+     * session keys.
+     */
+
+    /**
+     * Set the cipher algorithm to be used for the specified session.
+     *
+     * @param sessionId the session id the call applies to
+     * @param algorithm the algorithm to use. The string conforms to JCA
+     * Standard Names for Cipher Transforms and is case insensitive. An
+     * example algorithm is "AES/CBC/PKCS5Padding".
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the algorithm cannot be set.
+     */
+    setCipherAlgorithm(SessionId sessionId, string algorithm)
+        generates (Status status);
+
+    /**
+     * Set the MAC algorithm to be used for computing hashes in a session.
+     *
+     * @param sessionId the session id the call applies to
+     * @param algorithm the algorithm to use. The string conforms to JCA
+     * Standard Names for Mac Algorithms and is case insensitive. An example MAC
+     * algorithm string is "HmacSHA256".
+     * @return status the status of the call. The status must be OK or one of the
+     * following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the algorithm cannot be set.
+     */
+    setMacAlgorithm(SessionId sessionId, string algorithm)
+        generates (Status status);
+
+    /**
+     * Encrypt the provided input buffer with the cipher algorithm specified by
+     * setCipherAlgorithm and the key selected by keyId, and return the
+     * encrypted data.
+     *
+     * @param sessionId the session id the call applies to
+     * @param keyId the ID of the key to use for encryption
+     * @param input the input data to encrypt
+     * @param iv the initialization vector to use for encryption
+     * @return status the status of the call. The status must be OK or one of the
+     * following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the encrypt operation cannot be performed.
+     * @return output the decrypted data
+     */
+    encrypt(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> input,
+            vec<uint8_t> iv) generates (Status status, vec<uint8_t> output);
+
+    /**
+     * Decrypt the provided input buffer with the cipher algorithm
+     * specified by setCipherAlgorithm and the key selected by keyId,
+     * and return the decrypted data.
+     *
+     * @param sessionId the session id the call applies to
+     * @param keyId the ID of the key to use for decryption
+     * @param input the input data to decrypt
+     * @param iv the initialization vector to use for decryption
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the decrypt operation cannot be
+     * performed.
+     * @return output the decrypted data
+     */
+    decrypt(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> input,
+            vec<uint8_t> iv) generates (Status status, vec<uint8_t> output);
+
+    /**
+     * Compute a signature over the provided message using the mac algorithm
+     * specified by setMacAlgorithm and the key selected by keyId and return
+     * the signature.
+     *
+     * @param sessionId the session id the call applies to
+     * @param keyId the ID of the key to use for decryption
+     * @param message the message to compute a signature over
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the sign operation cannot be
+     * performed.
+     * @return signature the computed signature
+     */
+    sign(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> message)
+        generates (Status status, vec<uint8_t> signature);
+
+    /**
+     * Compute a hash of the provided message using the mac algorithm specified
+     * by setMacAlgorithm and the key selected by keyId, and compare with the
+     * expected result.
+     *
+     * @param sessionId the session id the call applies to
+     * @param keyId the ID of the key to use for decryption
+     * @param message the message to compute a hash of
+     * @param signature the signature to verify
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the verify operation cannot be
+     * performed.
+     * @return match true if the signature is verified positively,
+     * false otherwise.
+     */
+    verify(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> message,
+            vec<uint8_t> signature) generates (Status status, bool match);
+
+    /**
+     * Compute an RSA signature on the provided message using the specified
+     * algorithm.
+     *
+     * @param sessionId the session id the call applies to
+     * @param algorithm the signing algorithm, such as "RSASSA-PSS-SHA1"
+     * or "PKCS1-BlockType1"
+     * @param message the message to compute the signature on
+     * @param wrappedKey the private key returned during provisioning as
+     * returned by provideProvisionResponse.
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is
+     * not opened, BAD_VALUE if any parameters are invalid or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the signRSA
+     * operation cannot be performed.
+     * @return signature the RSA signature computed over the message
+     */
+    signRSA(SessionId sessionId, string algorithm, vec<uint8_t> message,
+        vec<uint8_t> wrappedkey)
+        generates (Status status, vec<uint8_t> signature);
+
+    /**
+     * Plugins call the following methods to deliver events to the
+     * java app.
+     */
+
+    /**
+     * Set a listener for a drm session. This allows the drm HAL to
+     * make asynchronous calls back to the client of IDrm.
+     *
+     * @param listener instance of IDrmPluginListener to receive the events
+     */
+    setListener(IDrmPluginListener listener);
+
+    /**
+     * Legacy event sending method, it sends events of various types using a
+     * single overloaded set of parameters. This form is deprecated.
+     *
+     * @param eventType the type of the event
+     * @param sessionId identifies the session the event originated from
+     * @param data event-specific data blob
+     */
+    sendEvent(EventType eventType, SessionId sessionId, vec<uint8_t> data);
+
+    /**
+     * Send a license expiration update to the listener. The expiration
+     * update indicates how long the current license is valid before it
+     * needs to be renewed.
+     *
+     * @param sessionId identifies the session the event originated from
+     * @param expiryTimeInMS the time when the keys need to be renewed.
+     * The time is in milliseconds, relative to the Unix epoch. A time of 0
+     * indicates that the keys never expire.
+     */
+     sendExpirationUpdate(SessionId sessionId, int64_t expiryTimeInMS);
+
+    /**
+     * Send a keys change event to the listener. The keys change event
+     * indicates the status of each key in the session. Keys can be
+     * indicated as being usable, expired, outputnotallowed or statuspending.
+     *
+     * @param sessionId identifies the session the event originated from
+     * @param keyStatusList indicates the status for each key ID in the
+     * session.
+     * @param hasNewUsableKey indicates if the event includes at least one
+     * key that has become usable.
+     */
+    sendKeysChange(SessionId sessionId, vec<KeyStatus> keyStatusList,
+            bool hasNewUsableKey);
+};
diff --git a/drm/1.0/IDrmPluginListener.hal b/drm/1.0/IDrmPluginListener.hal
new file mode 100644
index 0000000..15ce008
--- /dev/null
+++ b/drm/1.0/IDrmPluginListener.hal
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 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.drm@1.0;
+
+import android.hardware.drm@1.0::types;
+
+/**
+ * Ref: frameworks/native/include/media/drm/DrmAPI.h:DrmPluginListener
+ */
+
+/**
+ * IDrmPluginListener is a listener interface for Drm events sent from an
+ * IDrmPlugin instance.
+ */
+interface IDrmPluginListener {
+
+    /**
+     * Legacy event sending method, it sends events of various types using a
+     * single overloaded set of parameters. This form is deprecated.
+     *
+     * @param eventType the type of the event
+     * @param sessionId identifies the session the event originated from
+     * @param data event-specific data blob
+     */
+    oneway sendEvent(EventType eventType, SessionId sessionId,
+            vec<uint8_t> data);
+
+    /**
+     * Send a license expiration update to the listener. The expiration
+     * update indicates how long the current keys are valid before they
+     * need to be renewed.
+     *
+     * @param sessionId identifies the session the event originated from
+     * @param expiryTimeInMS the time when the keys need to be renewed.
+     * The time is in milliseconds, relative to the Unix epoch. A time
+     * of 0 indicates that the keys never expire.
+     */
+    oneway sendExpirationUpdate(SessionId sessionId, int64_t expiryTimeInMS);
+
+    /**
+     * Send a keys change event to the listener. The keys change event
+     * indicates the status of each key in the session. Keys can be
+     * indicated as being usable, expired, outputnotallowed or statuspending.
+     *
+     * @param sessionId identifies the session the event originated from
+     * @param keyStatusList indicates the status for each key ID in the
+     * session.
+     * @param hasNewUsableKey indicates if the event includes at least one
+     * key that has become usable.
+     */
+    oneway sendKeysChange(SessionId sessionId, vec<KeyStatus> keyStatusList,
+            bool hasNewUsableKey);
+};
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index 87a0019..ac5b90a 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -14,6 +14,8 @@
 # limitations under the License.
 
 
+############# Build legacy drm service ############
+
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -24,16 +26,14 @@
   service.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
+  android.hardware.drm@1.0 \
+  android.hidl.memory@1.0 \
   libhidlbase \
   libhidltransport \
-  liblog \
-  libhwbinder \
-  libutils \
   libhardware \
-  android.hardware.drm.drm@1.0 \
-  android.hardware.drm.crypto@1.0 \
-  android.hidl.memory@1.0 \
-
+  libhwbinder \
+  liblog \
+  libutils \
 
 LOCAL_C_INCLUDES := \
   hardware/interfaces/drm
@@ -43,3 +43,37 @@
 LOCAL_32_BIT_ONLY := true
 
 include $(BUILD_EXECUTABLE)
+
+############# Build legacy drm impl library ############
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.drm@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    DrmFactory.cpp \
+    DrmPlugin.cpp \
+    CryptoFactory.cpp \
+    CryptoPlugin.cpp \
+    TypeConvert.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.drm@1.0 \
+    android.hidl.memory@1.0 \
+    libhidlbase \
+    libhidlmemory \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libmediadrm \
+    libstagefright_foundation \
+    libutils \
+
+LOCAL_C_INCLUDES := \
+    frameworks/native/include \
+    frameworks/av/include
+
+# TODO: The legacy DRM plugins only support 32-bit. They need
+# to be migrated to 64-bit (b/18948909)
+LOCAL_32_BIT_ONLY := true
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/CryptoFactory.cpp b/drm/1.0/default/CryptoFactory.cpp
new file mode 100644
index 0000000..02084e7
--- /dev/null
+++ b/drm/1.0/default/CryptoFactory.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 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 "CryptoFactory.h"
+#include "CryptoPlugin.h"
+#include "TypeConvert.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    CryptoFactory::CryptoFactory() :
+        loader("/vendor/lib/mediadrm", "createCryptoFactory") {
+    }
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoFactory follow.
+    Return<bool> CryptoFactory::isCryptoSchemeSupported(
+            const hidl_array<uint8_t, 16>& uuid) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<void> CryptoFactory::createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            const hidl_vec<uint8_t>& initData, createPlugin_cb _hidl_cb) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                android::CryptoPlugin *legacyPlugin = NULL;
+                status_t status = loader.getFactory(i)->createPlugin(uuid.data(),
+                        initData.data(), initData.size(), &legacyPlugin);
+                CryptoPlugin *newPlugin = NULL;
+                if (legacyPlugin == NULL) {
+                    ALOGE("Crypto legacy HAL: failed to create crypto plugin");
+                } else {
+                    newPlugin = new CryptoPlugin(legacyPlugin);
+                }
+                _hidl_cb(toStatus(status), newPlugin);
+                return Void();
+            }
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, NULL);
+        return Void();
+    }
+
+    ICryptoFactory* HIDL_FETCH_ICryptoFactory(const char* /* name */) {
+        return new CryptoFactory();
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/CryptoFactory.h b/drm/1.0/default/CryptoFactory.h
new file mode 100644
index 0000000..412b557
--- /dev/null
+++ b/drm/1.0/default/CryptoFactory.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
+#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <hidl/Status.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/PluginLoader.h>
+#include <media/SharedLibrary.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::ICryptoFactory;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct CryptoFactory : public ICryptoFactory {
+    CryptoFactory();
+    virtual ~CryptoFactory() {}
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoFactory follow.
+
+    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
+            override;
+
+    Return<void> createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            const hidl_vec<uint8_t>& initData, createPlugin_cb _hidl_cb)
+            override;
+
+private:
+    android::PluginLoader<android::CryptoFactory> loader;
+
+    CryptoFactory(const CryptoFactory &) = delete;
+    void operator=(const CryptoFactory &) = delete;
+};
+
+extern "C" ICryptoFactory* HIDL_FETCH_ICryptoFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
new file mode 100644
index 0000000..073f030
--- /dev/null
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 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 "CryptoPlugin.h"
+#include "TypeConvert.h"
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/Log.h>
+
+using android::hardware::hidl_memory;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin follow
+    Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
+            const hidl_string& mime) {
+        return mLegacyPlugin->requiresSecureDecoderComponent(mime);
+    }
+
+    Return<void> CryptoPlugin::notifyResolution(uint32_t width,
+            uint32_t height) {
+        mLegacyPlugin->notifyResolution(width, height);
+        return Void();
+    }
+
+    Return<Status> CryptoPlugin::setMediaDrmSession(
+            const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->setMediaDrmSession(toVector(sessionId)));
+    }
+
+    Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base) {
+        mSharedBufferBase = mapMemory(base);
+        return Void();
+    }
+
+    Return<void> CryptoPlugin::decrypt(bool secure,
+            const hidl_array<uint8_t, 16>& keyId,
+            const hidl_array<uint8_t, 16>& iv, Mode mode,
+            const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
+            const SharedBuffer& source, uint64_t offset,
+            const DestinationBuffer& destination,
+            decrypt_cb _hidl_cb) {
+
+        android::CryptoPlugin::Mode legacyMode;
+        switch(mode) {
+        case Mode::UNENCRYPTED:
+            legacyMode = android::CryptoPlugin::kMode_Unencrypted;
+            break;
+        case Mode::AES_CTR:
+            legacyMode = android::CryptoPlugin::kMode_AES_CTR;
+            break;
+        case Mode::AES_CBC_CTS:
+            legacyMode = android::CryptoPlugin::kMode_AES_WV;
+            break;
+        case Mode::AES_CBC:
+            legacyMode = android::CryptoPlugin::kMode_AES_CBC;
+            break;
+        }
+        android::CryptoPlugin::Pattern legacyPattern;
+        legacyPattern.mEncryptBlocks = pattern.encryptBlocks;
+        legacyPattern.mSkipBlocks = pattern.skipBlocks;
+
+        android::CryptoPlugin::SubSample *legacySubSamples =
+            new android::CryptoPlugin::SubSample[subSamples.size()];
+
+        for (size_t i = 0; i < subSamples.size(); i++) {
+            legacySubSamples[i].mNumBytesOfClearData
+                = subSamples[i].numBytesOfClearData;
+            legacySubSamples[i].mNumBytesOfEncryptedData
+                = subSamples[i].numBytesOfEncryptedData;
+        }
+
+        AString detailMessage;
+
+        if (source.offset + offset + source.size > mSharedBufferBase->getSize()) {
+            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+            return Void();
+        }
+
+        uint8_t *base = static_cast<uint8_t *>
+                (static_cast<void *>(mSharedBufferBase->getPointer()));
+        void *srcPtr = static_cast<void *>(base + source.offset + offset);
+
+        void *destPtr = NULL;
+        if (destination.type == BufferType::SHARED_MEMORY) {
+            const SharedBuffer& destBuffer = destination.nonsecureMemory;
+            if (destBuffer.offset + destBuffer.size > mSharedBufferBase->getSize()) {
+                _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+                return Void();
+            }
+            destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
+        } else if (destination.type == BufferType::NATIVE_HANDLE) {
+            native_handle_t *handle = const_cast<native_handle_t *>(
+                    destination.secureMemory.getNativeHandle());
+            destPtr = static_cast<void *>(handle);
+        }
+        ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
+                legacyMode, legacyPattern, srcPtr, legacySubSamples,
+                subSamples.size(), destPtr, &detailMessage);
+
+        delete[] legacySubSamples;
+
+        uint32_t status;
+        uint32_t bytesWritten;
+
+        if (result >= 0) {
+            status = android::OK;
+            bytesWritten = result;
+        } else {
+            status = -result;
+            bytesWritten = 0;
+        }
+
+        _hidl_cb(toStatus(status), bytesWritten, detailMessage.c_str());
+        return Void();
+    }
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/CryptoPlugin.h b/drm/1.0/default/CryptoPlugin.h
new file mode 100644
index 0000000..f805f09
--- /dev/null
+++ b/drm/1.0/default/CryptoPlugin.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
+#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <hidl/Status.h>
+#include <media/hardware/CryptoAPI.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::V1_0::Mode;
+using ::android::hardware::drm::V1_0::Pattern;
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+struct CryptoPlugin : public ICryptoPlugin {
+    CryptoPlugin(android::CryptoPlugin *plugin) : mLegacyPlugin(plugin) {}
+
+    ~CryptoPlugin() {delete mLegacyPlugin;}
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin
+    // follow.
+
+    Return<bool> requiresSecureDecoderComponent(const hidl_string& mime)
+            override;
+
+    Return<void> notifyResolution(uint32_t width, uint32_t height) override;
+
+    Return<Status> setMediaDrmSession(const hidl_vec<uint8_t>& sessionId)
+            override;
+
+    Return<void> setSharedBufferBase(const ::android::hardware::hidl_memory& base)
+            override;
+
+    Return<void> decrypt(bool secure, const hidl_array<uint8_t, 16>& keyId,
+            const hidl_array<uint8_t, 16>& iv, Mode mode, const Pattern& pattern,
+            const hidl_vec<SubSample>& subSamples, const SharedBuffer& source,
+            uint64_t offset, const DestinationBuffer& destination,
+            decrypt_cb _hidl_cb) override;
+
+private:
+    android::CryptoPlugin *mLegacyPlugin;
+    sp<IMemory> mSharedBufferBase;
+
+    CryptoPlugin() = delete;
+    CryptoPlugin(const CryptoPlugin &) = delete;
+    void operator=(const CryptoPlugin &) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
diff --git a/drm/1.0/default/DrmFactory.cpp b/drm/1.0/default/DrmFactory.cpp
new file mode 100644
index 0000000..cba2c99
--- /dev/null
+++ b/drm/1.0/default/DrmFactory.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 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 "DrmFactory.h"
+#include "DrmPlugin.h"
+#include "TypeConvert.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    DrmFactory::DrmFactory() :
+        loader("/vendor/lib/mediadrm", "createDrmFactory") {
+    }
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmFactory follow.
+    Return<bool> DrmFactory::isCryptoSchemeSupported (
+            const hidl_array<uint8_t, 16>& uuid) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<bool> DrmFactory::isContentTypeSupported (
+            const hidl_string& mimeType) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isContentTypeSupported(String8(mimeType.c_str()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<void> DrmFactory::createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            createPlugin_cb _hidl_cb) {
+
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                android::DrmPlugin *legacyPlugin = NULL;
+                status_t status = loader.getFactory(i)->createDrmPlugin(
+                        uuid.data(), &legacyPlugin);
+                DrmPlugin *newPlugin = NULL;
+                if (legacyPlugin == NULL) {
+                    ALOGE("Drm legacy HAL: failed to create drm plugin");
+                } else {
+                    newPlugin = new DrmPlugin(legacyPlugin);
+                }
+                _hidl_cb(toStatus(status), newPlugin);
+                return Void();
+            }
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, NULL);
+        return Void();
+    }
+
+    IDrmFactory* HIDL_FETCH_IDrmFactory(const char* /* name */) {
+        return new DrmFactory();
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/DrmFactory.h b/drm/1.0/default/DrmFactory.h
new file mode 100644
index 0000000..78b7f6e
--- /dev/null
+++ b/drm/1.0/default/DrmFactory.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
+#define ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
+
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <hidl/Status.h>
+#include <media/drm/DrmAPI.h>
+#include <media/PluginLoader.h>
+#include <media/SharedLibrary.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DrmFactory : public IDrmFactory {
+    DrmFactory();
+    virtual ~DrmFactory() {}
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmFactory follow.
+
+    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
+            override;
+
+    Return<bool> isContentTypeSupported(const hidl_string &mimeType)
+            override;
+
+    Return<void> createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            createPlugin_cb _hidl_cb) override;
+
+private:
+    android::PluginLoader<android::DrmFactory> loader;
+
+    DrmFactory(const DrmFactory &) = delete;
+    void operator=(const DrmFactory &) = delete;
+};
+
+extern "C" IDrmFactory* HIDL_FETCH_IDrmFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
new file mode 100644
index 0000000..9204fc5
--- /dev/null
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2016 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 <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include "DrmPlugin.h"
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmPlugin follow.
+
+    Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
+        Vector<uint8_t> legacySessionId;
+        status_t status = mLegacyPlugin->openSession(legacySessionId);
+        _hidl_cb(toStatus(status), toHidlVec(legacySessionId));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->closeSession(toVector(sessionId)));
+    }
+
+    Return<void> DrmPlugin::getKeyRequest(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& initData, const hidl_string& mimeType,
+            KeyType keyType, const hidl_vec<KeyValue>& optionalParameters,
+            getKeyRequest_cb _hidl_cb) {
+
+        status_t status = android::OK;
+
+        android::DrmPlugin::KeyType legacyKeyType;
+        switch(keyType) {
+        case KeyType::OFFLINE:
+            legacyKeyType = android::DrmPlugin::kKeyType_Offline;
+            break;
+        case KeyType::STREAMING:
+            legacyKeyType = android::DrmPlugin::kKeyType_Streaming;
+            break;
+        case KeyType::RELEASE:
+            legacyKeyType = android::DrmPlugin::kKeyType_Release;
+            break;
+        default:
+            status = android::BAD_VALUE;
+            break;
+        }
+
+        Vector<uint8_t> legacyRequest;
+        KeyRequestType requestType = KeyRequestType::UNKNOWN;
+        String8 defaultUrl;
+
+        if (status == android::OK) {
+            android::KeyedVector<String8, String8> legacyOptionalParameters;
+            for (size_t i = 0; i < optionalParameters.size(); i++) {
+                legacyOptionalParameters.add(String8(optionalParameters[i].key),
+                        String8(optionalParameters[i].value));
+            }
+
+            android::DrmPlugin::KeyRequestType legacyRequestType =
+                    android::DrmPlugin::kKeyRequestType_Unknown;
+
+            status_t status = mLegacyPlugin->getKeyRequest(toVector(scope),
+                    toVector(initData), String8(mimeType), legacyKeyType,
+                    legacyOptionalParameters, legacyRequest, defaultUrl,
+                    &legacyRequestType);
+
+            switch(legacyRequestType) {
+            case android::DrmPlugin::kKeyRequestType_Initial:
+                requestType = KeyRequestType::INITIAL;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Renewal:
+                requestType = KeyRequestType::RENEWAL;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Release:
+                requestType = KeyRequestType::RELEASE;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Unknown:
+                status = android::BAD_VALUE;
+                break;
+            }
+        }
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest), requestType,
+                 defaultUrl.string());
+        return Void();
+    }
+
+    Return<void> DrmPlugin::provideKeyResponse(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& response, provideKeyResponse_cb _hidl_cb) {
+
+        Vector<uint8_t> keySetId;
+        status_t status = mLegacyPlugin->provideKeyResponse(toVector(scope),
+                toVector(response), keySetId);
+        _hidl_cb(toStatus(status), toHidlVec(keySetId));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::removeKeys(const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->removeKeys(toVector(sessionId)));
+    }
+
+    Return<Status> DrmPlugin::restoreKeys(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keySetId) {
+        status_t legacyStatus = mLegacyPlugin->restoreKeys(toVector(sessionId),
+                toVector(keySetId));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::queryKeyStatus(const hidl_vec<uint8_t>& sessionId,
+            queryKeyStatus_cb _hidl_cb) {
+
+        android::KeyedVector<String8, String8> legacyInfoMap;
+        status_t status = mLegacyPlugin->queryKeyStatus(toVector(sessionId),
+                legacyInfoMap);
+
+        Vector<KeyValue> infoMapVec;
+        for (size_t i = 0; i < legacyInfoMap.size(); i++) {
+            KeyValue keyValuePair;
+            keyValuePair.key = String8(legacyInfoMap.keyAt(i));
+            keyValuePair.value = String8(legacyInfoMap.valueAt(i));
+            infoMapVec.push_back(keyValuePair);
+        }
+        _hidl_cb(toStatus(status), toHidlVec(infoMapVec));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getProvisionRequest(
+            const hidl_string& certificateType,
+            const hidl_string& certificateAuthority,
+            getProvisionRequest_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyRequest;
+        String8 legacyDefaultUrl;
+        status_t status = mLegacyPlugin->getProvisionRequest(
+                String8(certificateType), String8(certificateAuthority),
+                legacyRequest, legacyDefaultUrl);
+
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest),
+                hidl_string(legacyDefaultUrl));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::provideProvisionResponse(
+            const hidl_vec<uint8_t>& response,
+            provideProvisionResponse_cb _hidl_cb) {
+
+        Vector<uint8_t> certificate;
+        Vector<uint8_t> wrappedKey;
+
+        status_t legacyStatus = mLegacyPlugin->provideProvisionResponse(
+                toVector(response), certificate, wrappedKey);
+
+        _hidl_cb(toStatus(legacyStatus), toHidlVec(certificate),
+                toHidlVec(wrappedKey));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
+        List<Vector<uint8_t> > legacySecureStops;
+        status_t status = mLegacyPlugin->getSecureStops(legacySecureStops);
+
+        Vector<SecureStop> secureStopsVec;
+        List<Vector<uint8_t> >::iterator iter = legacySecureStops.begin();
+
+        while (iter != legacySecureStops.end()) {
+            SecureStop secureStop;
+            secureStop.opaqueData = toHidlVec(*iter++);
+            secureStopsVec.push_back(secureStop);
+        }
+
+        _hidl_cb(toStatus(status), toHidlVec(secureStopsVec));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
+            getSecureStop_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySecureStop;
+        status_t status = mLegacyPlugin->getSecureStop(toVector(secureStopId),
+                legacySecureStop);
+
+        SecureStop secureStop;
+        secureStop.opaqueData = toHidlVec(legacySecureStop);
+        _hidl_cb(toStatus(status), secureStop);
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::releaseAllSecureStops() {
+        return toStatus(mLegacyPlugin->releaseAllSecureStops());
+    }
+
+    Return<Status> DrmPlugin::releaseSecureStop(
+            const hidl_vec<uint8_t>& secureStopId) {
+        status_t legacyStatus =
+            mLegacyPlugin->releaseSecureStops(toVector(secureStopId));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::getPropertyString(const hidl_string& propertyName,
+            getPropertyString_cb _hidl_cb) {
+        String8 legacyValue;
+        status_t status = mLegacyPlugin->getPropertyString(
+                String8(propertyName), legacyValue);
+        _hidl_cb(toStatus(status), legacyValue.string());
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getPropertyByteArray(const hidl_string& propertyName,
+            getPropertyByteArray_cb _hidl_cb) {
+        Vector<uint8_t> legacyValue;
+        status_t status = mLegacyPlugin->getPropertyByteArray(
+                String8(propertyName), legacyValue);
+        _hidl_cb(toStatus(status), toHidlVec(legacyValue));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::setPropertyString(const hidl_string& propertyName,
+            const hidl_string& value) {
+        status_t legacyStatus =
+            mLegacyPlugin->setPropertyString(String8(propertyName),
+                    String8(value));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setPropertyByteArray(
+            const hidl_string& propertyName, const hidl_vec<uint8_t>& value) {
+        status_t legacyStatus =
+            mLegacyPlugin->setPropertyByteArray(String8(propertyName),
+                    toVector(value));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setCipherAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        status_t legacyStatus =
+            mLegacyPlugin->setCipherAlgorithm(toVector(sessionId),
+                String8(algorithm));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setMacAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        status_t legacyStatus =
+            mLegacyPlugin->setMacAlgorithm(toVector(sessionId),
+                String8(algorithm));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::encrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, encrypt_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyOutput;
+        status_t status = mLegacyPlugin->encrypt(toVector(sessionId),
+                toVector(keyId), toVector(input), toVector(iv), legacyOutput);
+        _hidl_cb(toStatus(status), toHidlVec(legacyOutput));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::decrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, decrypt_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyOutput;
+        status_t status = mLegacyPlugin->decrypt(toVector(sessionId),
+                toVector(keyId), toVector(input), toVector(iv), legacyOutput);
+        _hidl_cb(toStatus(status), toHidlVec(legacyOutput));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sign(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            sign_cb _hidl_cb) {
+        Vector<uint8_t> legacySignature;
+        status_t status = mLegacyPlugin->sign(toVector(sessionId),
+                toVector(keyId), toVector(message), legacySignature);
+        _hidl_cb(toStatus(status), toHidlVec(legacySignature));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::verify(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& signature, verify_cb _hidl_cb) {
+
+        bool match;
+        status_t status = mLegacyPlugin->verify(toVector(sessionId),
+                toVector(keyId), toVector(message), toVector(signature),
+                match);
+        _hidl_cb(toStatus(status), match);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::signRSA(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& wrappedKey, signRSA_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySignature;
+        status_t status = mLegacyPlugin->signRSA(toVector(sessionId),
+                String8(algorithm), toVector(message), toVector(wrappedKey),
+                legacySignature);
+        _hidl_cb(toStatus(status), toHidlVec(legacySignature));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::setListener(const sp<IDrmPluginListener>& listener) {
+        mListener = listener;
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
+        mListener->sendEvent(eventType, sessionId, data);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendExpirationUpdate(
+            const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
+        mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+        mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+        return Void();
+    }
+
+
+    // Methods from android::DrmPluginListener
+
+    void DrmPlugin::sendEvent(android::DrmPlugin::EventType legacyEventType,
+            int /*unused*/, Vector<uint8_t> const *sessionId,
+            Vector<uint8_t> const *data) {
+
+        EventType eventType;
+        bool sendEvent = true;
+        switch(legacyEventType) {
+        case android::DrmPlugin::kDrmPluginEventProvisionRequired:
+            eventType = EventType::PROVISION_REQUIRED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventKeyNeeded:
+            eventType = EventType::KEY_NEEDED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventKeyExpired:
+            eventType = EventType::KEY_EXPIRED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventVendorDefined:
+            eventType = EventType::VENDOR_DEFINED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventSessionReclaimed:
+            eventType = EventType::SESSION_RECLAIMED;
+            break;
+        default:
+            sendEvent = false;
+            break;
+        }
+        if (sendEvent) {
+            mListener->sendEvent(eventType, toHidlVec(*sessionId),
+                    toHidlVec(*data));
+        }
+    }
+
+    void DrmPlugin::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+            int64_t expiryTimeInMS) {
+        mListener->sendExpirationUpdate(toHidlVec(*sessionId), expiryTimeInMS);
+    }
+
+    void DrmPlugin::sendKeysChange(Vector<uint8_t> const *sessionId,
+            Vector<android::DrmPlugin::KeyStatus> const *legacyKeyStatusList,
+            bool hasNewUsableKey) {
+
+        Vector<KeyStatus> keyStatusVec;
+        for (size_t i = 0; i < legacyKeyStatusList->size(); i++) {
+            const android::DrmPlugin::KeyStatus &legacyKeyStatus =
+                legacyKeyStatusList->itemAt(i);
+
+            KeyStatus keyStatus;
+
+            switch(legacyKeyStatus.mType) {
+            case android::DrmPlugin::kKeyStatusType_Usable:
+                keyStatus.type = KeyStatusType::USABLE;
+                break;
+            case android::DrmPlugin::kKeyStatusType_Expired:
+                keyStatus.type = KeyStatusType::EXPIRED;
+                break;
+            case android::DrmPlugin::kKeyStatusType_OutputNotAllowed:
+                keyStatus.type = KeyStatusType::OUTPUTNOTALLOWED;
+                break;
+            case android::DrmPlugin::kKeyStatusType_StatusPending:
+                keyStatus.type = KeyStatusType::STATUSPENDING;
+                break;
+            case android::DrmPlugin::kKeyStatusType_InternalError:
+            default:
+                keyStatus.type = KeyStatusType::INTERNALERROR;
+                break;
+            }
+
+            keyStatus.keyId = toHidlVec(legacyKeyStatus.mKeyId);
+            keyStatusVec.push_back(keyStatus);
+        }
+        mListener->sendKeysChange(toHidlVec(*sessionId),
+                toHidlVec(keyStatusVec), hasNewUsableKey);
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/DrmPlugin.h b/drm/1.0/default/DrmPlugin.h
new file mode 100644
index 0000000..dce6c0c
--- /dev/null
+++ b/drm/1.0/default/DrmPlugin.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
+#define ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
+
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/IDrmPluginListener.h>
+#include <hidl/Status.h>
+#include <media/drm/DrmAPI.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::IDrmPluginListener;
+using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::drm::V1_0::SecureStop;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DrmPlugin : public IDrmPlugin, android::DrmPluginListener {
+
+    DrmPlugin(android::DrmPlugin *plugin) : mLegacyPlugin(plugin) {}
+    ~DrmPlugin() {delete mLegacyPlugin;}
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmPlugin follow.
+
+    Return<void> openSession(openSession_cb _hidl_cb) override;
+
+    Return<Status> closeSession(const hidl_vec<uint8_t>& sessionId) override;
+
+    Return<void> getKeyRequest(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& initData, const hidl_string& mimeType,
+            KeyType keyType, const hidl_vec<KeyValue>& optionalParameters,
+            getKeyRequest_cb _hidl_cb) override;
+
+    Return<void> provideKeyResponse(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& response, provideKeyResponse_cb _hidl_cb)
+            override;
+
+    Return<Status> removeKeys(const hidl_vec<uint8_t>& sessionId) override;
+
+    Return<Status> restoreKeys(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keySetId) override;
+
+    Return<void> queryKeyStatus(const hidl_vec<uint8_t>& sessionId,
+            queryKeyStatus_cb _hidl_cb) override;
+
+    Return<void> getProvisionRequest(const hidl_string& certificateType,
+            const hidl_string& certificateAuthority,
+            getProvisionRequest_cb _hidl_cb) override;
+
+    Return<void> provideProvisionResponse(const hidl_vec<uint8_t>& response,
+            provideProvisionResponse_cb _hidl_cb) override;
+
+    Return<void> getSecureStops(getSecureStops_cb _hidl_cb) override;
+
+    Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId,
+            getSecureStop_cb _hidl_cb) override;
+
+    Return<Status> releaseAllSecureStops() override;
+
+    Return<Status> releaseSecureStop(const hidl_vec<uint8_t>& secureStopId)
+            override;
+
+    Return<void> getPropertyString(const hidl_string& propertyName,
+            getPropertyString_cb _hidl_cb) override;
+
+    Return<void> getPropertyByteArray(const hidl_string& propertyName,
+            getPropertyByteArray_cb _hidl_cb) override;
+
+    Return<Status> setPropertyString(const hidl_string& propertyName,
+            const hidl_string& value) override;
+
+    Return<Status> setPropertyByteArray(const hidl_string& propertyName,
+            const hidl_vec<uint8_t>& value) override;
+
+    Return<Status> setCipherAlgorithm(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm) override;
+
+    Return<Status> setMacAlgorithm(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm) override;
+
+    Return<void> encrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, encrypt_cb _hidl_cb) override;
+
+    Return<void> decrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, decrypt_cb _hidl_cb) override;
+
+    Return<void> sign(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            sign_cb _hidl_cb) override;
+
+    Return<void> verify(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& signature, verify_cb _hidl_cb) override;
+
+    Return<void> signRSA(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& wrappedkey, signRSA_cb _hidl_cb) override;
+
+    Return<void> setListener(const sp<IDrmPluginListener>& listener) override;
+
+    Return<void> sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data)
+            override;
+
+    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+            int64_t expiryTimeInMS) override;
+
+    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey)
+            override;
+
+    // Methods from android::DrmPluginListener follow
+
+    virtual void sendEvent(android::DrmPlugin::EventType eventType, int extra,
+            Vector<uint8_t> const *sessionId, Vector<uint8_t> const *data);
+
+    virtual void sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+            int64_t expiryTimeInMS);
+
+    virtual void sendKeysChange(Vector<uint8_t> const *sessionId,
+            Vector<android::DrmPlugin::KeyStatus> const *keyStatusList,
+            bool hasNewUsableKey);
+
+private:
+    android::DrmPlugin *mLegacyPlugin;
+    sp<IDrmPluginListener> mListener;
+
+    DrmPlugin() = delete;
+    DrmPlugin(const DrmPlugin &) = delete;
+    void operator=(const DrmPlugin &) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
diff --git a/drm/1.0/default/TypeConvert.cpp b/drm/1.0/default/TypeConvert.cpp
new file mode 100644
index 0000000..52cc503
--- /dev/null
+++ b/drm/1.0/default/TypeConvert.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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 "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus) {
+    Status status;
+    switch(legacyStatus) {
+    case android::OK:
+        status = Status::OK;
+        break;
+    case android::ERROR_DRM_NO_LICENSE:
+        status = Status::ERROR_DRM_NO_LICENSE;
+        break;
+    case android::ERROR_DRM_LICENSE_EXPIRED:
+        status = Status::ERROR_DRM_LICENSE_EXPIRED;
+        break;
+    case android::ERROR_DRM_SESSION_NOT_OPENED:
+        status = Status::ERROR_DRM_SESSION_NOT_OPENED;
+        break;
+    case android::ERROR_DRM_CANNOT_HANDLE:
+        status = Status::ERROR_DRM_CANNOT_HANDLE;
+        break;
+    case android::ERROR_DRM_TAMPER_DETECTED:
+        status = Status::ERROR_DRM_INVALID_STATE;
+        break;
+    case android::BAD_VALUE:
+        status = Status::BAD_VALUE;
+        break;
+    case android::ERROR_DRM_NOT_PROVISIONED:
+        status = Status::ERROR_DRM_NOT_PROVISIONED;
+        break;
+    case android::ERROR_DRM_RESOURCE_BUSY:
+        status = Status::ERROR_DRM_RESOURCE_BUSY;
+        break;
+    case android::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+        status = Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+        break;
+    case android::ERROR_DRM_DEVICE_REVOKED:
+        status = Status::ERROR_DRM_DEVICE_REVOKED;
+        break;
+    default:
+        ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN",
+            legacyStatus);
+        status = Status::ERROR_DRM_UNKNOWN;
+        break;
+    }
+    return status;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/TypeConvert.h b/drm/1.0/default/TypeConvert.h
new file mode 100644
index 0000000..107fda5
--- /dev/null
+++ b/drm/1.0/default/TypeConvert.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
+#define ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
+
+#include <android/hardware/drm/1.0/types.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+template<typename T> const hidl_vec<T> toHidlVec(const Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(const_cast<T *>(Vector.array()), Vector.size());
+    return vec;
+}
+
+template<typename T> hidl_vec<T> toHidlVec(Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(Vector.editArray(), Vector.size());
+    return vec;
+}
+
+template<typename T> const Vector<T> toVector(const hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return *const_cast<const Vector<T> *>(&vector);
+}
+
+template<typename T> Vector<T> toVector(hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return vector;
+}
+
+template<typename T, size_t SIZE> const Vector<T> toVector(
+        const hidl_array<T, SIZE> &array) {
+    Vector<T> vector;
+    vector.appendArray(array.data(), array.size());
+    return vector;
+}
+
+template<typename T, size_t SIZE> Vector<T> toVector(
+        hidl_array<T, SIZE> &array) {
+    Vector<T> vector;
+    vector.appendArray(array.data(), array.size());
+    return vector;
+}
+
+Status toStatus(status_t legacyStatus);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
diff --git a/drm/1.0/default/service.cpp b/drm/1.0/default/service.cpp
index 3531e03..fba56ec 100644
--- a/drm/1.0/default/service.cpp
+++ b/drm/1.0/default/service.cpp
@@ -16,8 +16,8 @@
 
 #define LOG_TAG "android.hardware.drm@1.0-service"
 
-#include <crypto/1.0/default/CryptoFactory.h>
-#include <drm/1.0/default/DrmFactory.h>
+#include <1.0/default/CryptoFactory.h>
+#include <1.0/default/DrmFactory.h>
 
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/LegacySupport.h>
@@ -26,8 +26,8 @@
 using android::hardware::joinRpcThreadpool;
 using android::hardware::registerPassthroughServiceImplementation;
 
-using android::hardware::drm::crypto::V1_0::ICryptoFactory;
-using android::hardware::drm::drm::V1_0::IDrmFactory;
+using android::hardware::drm::V1_0::ICryptoFactory;
+using android::hardware::drm::V1_0::IDrmFactory;
 
 int main() {
     ALOGD("android.hardware.drm@1.0-service starting...");
diff --git a/drm/1.0/types.hal b/drm/1.0/types.hal
new file mode 100644
index 0000000..33bbf9a
--- /dev/null
+++ b/drm/1.0/types.hal
@@ -0,0 +1,336 @@
+/**
+ * Copyright (C) 2016 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.drm@1.0;
+
+enum Status : uint32_t {
+    /**
+     * The DRM plugin must return OK when an operation completes without any
+     * errors.
+     */
+    OK,
+
+    /**
+     * The DRM plugin must return ERROR_DRM_NO_LICENSE, when decryption is
+     * attempted and no license keys have been provided.
+     */
+    ERROR_DRM_NO_LICENSE,
+
+    /**
+     * ERROR_DRM_LICENSE_EXPIRED must be returned when an attempt is made
+     * to use a license and the keys in that license have expired.
+     */
+    ERROR_DRM_LICENSE_EXPIRED,
+
+    /**
+     * The DRM plugin must return ERROR_DRM_SESSION_NOT_OPENED when an
+     * attempt is made to use a session that has not been opened.
+     */
+    ERROR_DRM_SESSION_NOT_OPENED,
+
+    /**
+     * The DRM plugin must return ERROR_DRM_CANNOT_HANDLE when an unsupported
+     * data format or operation is attempted.
+     */
+    ERROR_DRM_CANNOT_HANDLE,
+
+    /**
+     * ERROR_DRM_INVALID_STATE must be returned when the device is in a state
+     * where it is not able to perform decryption.
+     */
+    ERROR_DRM_INVALID_STATE,
+
+    /**
+     * The DRM plugin must return BAD_VALUE whenever an illegal parameter is
+     * passed to one of the interface functions.
+     */
+    BAD_VALUE,
+
+    /**
+     * The DRM plugin must return ERROR_DRM_NOT_PROVISIONED from getKeyRequest,
+     * openSession or provideKeyResponse when the device has not yet been
+     * provisioned.
+     */
+    ERROR_DRM_NOT_PROVISIONED,
+
+    /**
+     * ERROR_DRM_RESOURCE_BUSY must be returned when resources, such as drm
+     * sessions or secure buffers are not available to perform a requested
+     * operation because they are already in use.
+     */
+    ERROR_DRM_RESOURCE_BUSY,
+
+    /**
+     * The DRM Plugin must return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION
+     * when the output protection level enabled on the device is not
+     * sufficient to meet the requirements in the license policy.  HDCP is an
+     * example of a form of output protection.
+     */
+    ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION,
+
+    /**
+     * The DRM Plugin must return ERROR_DRM_DEVICE_REVOKED from
+     * provideProvisionResponse and provideKeyResponse if the response indicates
+     * that the device has been revoked. Device revocation means that the device
+     * is no longer permitted to play content.
+     */
+    ERROR_DRM_DEVICE_REVOKED,
+
+    /**
+     * ERROR_DRM_UNKNOWN must be returned when a fatal failure occurs and no
+     * other defined error is appropriate.
+     */
+    ERROR_DRM_UNKNOWN,
+};
+
+
+/**
+ * EventType enumerates the events that can be delivered by sendEvent
+ */
+enum EventType : uint32_t {
+    /**
+     * This event type indicates that the app needs to request a certificate
+     * from the provisioning server. The request message data is obtained using
+     * getProvisionRequest().
+     */
+    PROVISION_REQUIRED,
+
+     /**
+     * This event type indicates that the app needs to request keys from a
+     * license server. The request message data is obtained using getKeyRequest.
+     */
+    KEY_NEEDED,
+
+    /**
+     * This event type indicates that the licensed usage duration for keys in a
+     * session has expired. The keys are no longer valid.
+     */
+    KEY_EXPIRED,
+
+    /**
+     * This event may indicate some specific vendor-defined condition, see your
+     * DRM provider documentation for details.
+     */
+    VENDOR_DEFINED,
+
+    /**
+     * This event indicates that a session opened by the app has been reclaimed
+     * by the resource manager.
+     */
+    SESSION_RECLAIMED,
+};
+
+enum KeyType : uint32_t {
+    /**
+     * Drm keys can be for offline content or for online streaming.
+     * Offline keys are persisted on the device and may be used when the device
+     * is disconnected from the network.
+     */
+    OFFLINE,
+
+    /**
+     * Keys for streaming are not persisted and require the device to be
+     * connected to the network for periodic renewal.
+     */
+    STREAMING,
+
+    /**
+     * The Release type is used to request that offline keys be no longer
+     * restricted to offline use.
+     */
+    RELEASE,
+};
+
+/**
+ * Enumerate KeyRequestTypes to allow an app to determine the type of a key
+ * request returned from getKeyRequest.
+ */
+enum KeyRequestType : uint32_t {
+    /**
+     * Key request type is for an initial license request
+     */
+    INITIAL,
+
+    /**
+     * Key request type is for license renewal. Renewal requests are used
+     * to extend the validity period for streaming keys.
+     */
+    RENEWAL,
+
+    /**
+     * Key request type is a release. A key release causes offline keys
+     * to become available for streaming.
+     */
+    RELEASE,
+
+    /**
+     * Key request type is unknown due to some error condition.
+     */
+    UNKNOWN,
+};
+
+/**
+ * Enumerate KeyStatusTypes which indicate the state of a key
+ */
+enum KeyStatusType : uint32_t {
+    /**
+     * The key is currently usable to decrypt media data.
+     */
+    USABLE,
+
+    /**
+     * The key is no longer usable to decrypt media data because its expiration
+     * time has passed.
+     */
+    EXPIRED,
+
+    /**
+     * The key is not currently usable to decrypt media data because its output
+     * requirements cannot currently be met.
+     */
+    OUTPUTNOTALLOWED,
+
+    /**
+     * The status of the key is not yet known and is being determined.
+     */
+    STATUSPENDING,
+
+    /**
+     * The key is not currently usable to decrypt media data because of an
+     * internal error in processing unrelated to input parameters.
+     */
+    INTERNALERROR,
+};
+
+typedef vec<uint8_t> SessionId;
+
+/**
+ * Used by sendKeysChange to report the usability status of each key to the
+ * app.
+ */
+struct KeyStatus
+{
+    vec<uint8_t> keyId;
+    KeyStatusType type;
+};
+
+/**
+ * Simulates a KeyedVector<String8, String8>
+ */
+struct KeyValue {
+    string key;
+    string value;
+};
+
+typedef vec<KeyValue> KeyedVector;
+
+/**
+ * Encapsulates a secure stop opaque object
+ */
+struct SecureStop {
+    vec<uint8_t> opaqueData;
+};
+
+typedef vec<uint8_t> SecureStopId;
+
+
+/**
+ * Enumerate the supported crypto modes
+ */
+enum Mode : uint32_t {
+    UNENCRYPTED = 0, // Samples are unencrypted
+    AES_CTR     = 1, // Samples are encrypted with AES CTR mode
+    AES_CBC_CTS = 2, // Samples are encrypted with AES CBC CTS mode
+    AES_CBC     = 3, // Samples are encrypted with AES CBC mode
+};
+
+/**
+ * A subsample consists of some number of bytes of clear (unencrypted)
+ * data followed by a number of bytes of encrypted data.
+ */
+struct SubSample {
+    uint32_t numBytesOfClearData;
+    uint32_t numBytesOfEncryptedData;
+};
+
+/**
+ * A crypto Pattern is a repeating sequence of encrypted and clear blocks
+ * occuring within the bytes indicated by mNumBytesOfEncryptedDatad bytes
+ * of a subsample. Patterns are used to reduce the CPU overhead of
+ * decrypting samples. As an example, HLS uses 1:9 patterns where every
+ * 10th block is encrypted.
+ */
+struct Pattern {
+    /**
+     * The number of blocks to be encrypted in the pattern. If zero,
+     * pattern encryption is inoperative.
+     */
+    uint32_t encryptBlocks;
+
+    /**
+     * The number of blocks to be skipped (left clear) in the pattern. If
+     * zero, pattern encryption is inoperative.
+     */
+    uint32_t skipBlocks;
+};
+
+enum BufferType : uint32_t {
+    SHARED_MEMORY = 0,
+    NATIVE_HANDLE = 1,
+};
+
+/**
+ * A SharedBuffer describes a decrypt buffer which is defined by an offset and
+ * a size.  The offset is relative to the shared memory base which is established
+ * using setSharedMemoryBase().
+ */
+struct SharedBuffer {
+    /**
+     * The offset from the shared memory base
+     */
+    uint64_t offset;
+
+    /**
+     * The size of the shared buffer in bytes
+     */
+    uint64_t size;
+};
+
+
+/**
+ * A decrypt destination buffer can be either normal user-space shared
+ * memory for the non-secure decrypt case, or it can be a secure buffer
+ * which is referenced by a native-handle. The native handle is allocated
+ * by the vendor's buffer allocator.
+ */
+struct DestinationBuffer {
+    /**
+     * The type of the buffer
+     */
+    BufferType type;
+
+    /**
+     * If type == SHARED_MEMORY, the decrypted data must be written
+     * to user-space non-secure shared memory.
+     */
+    SharedBuffer nonsecureMemory;
+
+    /**
+     * If type == NATIVE_HANDLE, the decrypted data must be written
+     * to secure memory referenced by the vendor's buffer allocator.
+     */
+    handle secureMemory;
+};