Implement client code to use Drm and Crypto HALs
This change adds DrmHal & CryptoHal classes that connect to the Treble
HAL interfaces for drm. These classes mirror the existing Drm and
Crypto classes that connect to the DrmPlugin and CryptoPlugin
interfaces. Having both allows mediadrmserver to run in either mode
while the HAL is stabilized.
The shared memory interfaces between mediaserver's ACodecBufferChannel
and ICrypto had to be reworked to use the Treble HALs. Specifically,
the shared memory path for returning decrypted buffers in the
non-secure case had to become separate instead of piggy-backing on the
source shared memory buffer. A separate shared memory destination
buffer is now allocated on the buffer channel. An abstraction for a
decrypt destination buffer was also introduced to clarify ICrypto's
decrypt method.
Tests: Playback using Play Movies and ExoPlayer works on angler
with and without the treble hal enabled.
bug: 32815560
Change-Id: I5a3dc84f99902eb8cf8eabab9ad074d307744950
diff --git a/include/media/Crypto.h b/include/media/Crypto.h
index 7d181d3..ce08f98 100644
--- a/include/media/Crypto.h
+++ b/include/media/Crypto.h
@@ -49,16 +49,11 @@
virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
- virtual ssize_t decrypt(
- DestinationType dstType,
- const uint8_t key[16],
- const uint8_t iv[16],
- CryptoPlugin::Mode mode,
- const CryptoPlugin::Pattern &pattern,
- const sp<IMemory> &sharedBuffer, size_t offset,
+ virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+ const sp<IMemory> &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- void *dstPtr,
- AString *errorDetailMsg);
+ const DestinationBuffer &destination, AString *errorDetailMsg);
private:
mutable Mutex mLock;
diff --git a/include/media/CryptoHal.h b/include/media/CryptoHal.h
new file mode 100644
index 0000000..1ace957
--- /dev/null
+++ b/include/media/CryptoHal.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CRYPTO_HAL_H_
+
+#define CRYPTO_HAL_H_
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <media/ICrypto.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+#include "SharedLibrary.h"
+
+namespace android {
+
+struct CryptoHal : public BnCrypto {
+ CryptoHal();
+ virtual ~CryptoHal();
+
+ virtual status_t initCheck() const;
+
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
+
+ virtual status_t createPlugin(
+ const uint8_t uuid[16], const void *data, size_t size);
+
+ virtual status_t destroyPlugin();
+
+ virtual bool requiresSecureDecoderComponent(
+ const char *mime) const;
+
+ virtual void notifyResolution(uint32_t width, uint32_t height);
+
+ virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+
+ virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+ const sp<IMemory> &source, size_t offset,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+ const ICrypto::DestinationBuffer &destination,
+ AString *errorDetailMsg);
+
+private:
+ mutable Mutex mLock;
+
+ sp<SharedLibrary> mLibrary;
+ sp<::android::hardware::drm::V1_0::ICryptoFactory> mFactory;
+ sp<::android::hardware::drm::V1_0::ICryptoPlugin> mPlugin;
+
+ /**
+ * mInitCheck is:
+ * NO_INIT if a plugin hasn't been created yet
+ * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+ * OK after a plugin has been created and mPlugin is valid
+ */
+ status_t mInitCheck;
+
+ void *mHeapBase;
+
+ sp<::android::hardware::drm::V1_0::ICryptoFactory>
+ makeCryptoFactory();
+ sp<::android::hardware::drm::V1_0::ICryptoPlugin>
+ makeCryptoPlugin(const uint8_t uuid[16], const void *initData,
+ size_t size);
+
+ status_t setHeapBase(const sp<IMemory> &sharedBuffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
+};
+
+} // namespace android
+
+#endif // CRYPTO_HAL_H_
diff --git a/include/media/DrmHal.h b/include/media/DrmHal.h
new file mode 100644
index 0000000..aaea2c9
--- /dev/null
+++ b/include/media/DrmHal.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_HAL_H_
+
+#define DRM_HAL_H_
+
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/IDrmPluginListener.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+
+#include <media/IDrm.h>
+#include <media/IDrmClient.h>
+#include <utils/threads.h>
+
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::IDrmPluginListener;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+namespace android {
+
+struct DrmSessionClientInterface;
+
+struct DrmHal : public BnDrm,
+ public IBinder::DeathRecipient,
+ public IDrmPluginListener {
+ DrmHal();
+ virtual ~DrmHal();
+
+ virtual status_t initCheck() const;
+
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType);
+
+ virtual status_t createPlugin(const uint8_t uuid[16]);
+
+ virtual status_t destroyPlugin();
+
+ virtual status_t openSession(Vector<uint8_t> &sessionId);
+
+ virtual status_t closeSession(Vector<uint8_t> const &sessionId);
+
+ virtual status_t
+ getKeyRequest(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &initData,
+ String8 const &mimeType, DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const &optionalParameters,
+ Vector<uint8_t> &request, String8 &defaultUrl,
+ DrmPlugin::KeyRequestType *keyRequestType);
+
+ virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId);
+
+ virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
+
+ virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId);
+
+ virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const;
+
+ virtual status_t getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaulUrl);
+
+ virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey);
+
+ virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
+ virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+
+ virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
+ virtual status_t releaseAllSecureStops();
+
+ virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
+ virtual status_t getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value ) const;
+ virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
+ virtual status_t setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value ) const;
+
+ virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+
+ virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+
+ virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual status_t decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual status_t sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature);
+
+ virtual status_t verify(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &signature,
+ bool &match);
+
+ virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature);
+
+ virtual status_t setListener(const sp<IDrmClient>& listener);
+
+ // Methods of IDrmPluginListener
+ Return<void> sendEvent(EventType eventType,
+ const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
+
+ Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+ int64_t expiryTimeInMS);
+
+ Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
+
+ virtual void binderDied(const wp<IBinder> &the_late_who);
+
+private:
+ static Mutex mLock;
+
+ sp<DrmSessionClientInterface> mDrmSessionClient;
+
+ sp<IDrmClient> mListener;
+ mutable Mutex mEventLock;
+ mutable Mutex mNotifyLock;
+
+ sp<IDrmFactory> mFactory;
+ sp<IDrmPlugin> mPlugin;
+
+ /**
+ * mInitCheck is:
+ * NO_INIT if a plugin hasn't been created yet
+ * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+ * OK after a plugin has been created and mPlugin is valid
+ */
+ status_t mInitCheck;
+
+ sp<IDrmFactory> makeDrmFactory();
+ sp<IDrmPlugin> makeDrmPlugin(const uint8_t uuid[16]);
+
+ void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmHal);
+};
+
+} // namespace android
+
+#endif // DRM_HAL_H_
diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h
index a4bfaf8..8990f4b 100644
--- a/include/media/ICrypto.h
+++ b/include/media/ICrypto.h
@@ -15,8 +15,9 @@
*/
#include <binder/IInterface.h>
-#include <media/stagefright/foundation/ABase.h>
+#include <cutils/native_handle.h>
#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/ABase.h>
#ifndef ANDROID_ICRYPTO_H_
@@ -47,21 +48,21 @@
virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
enum DestinationType {
- kDestinationTypeVmPointer, // non-secure
- kDestinationTypeOpaqueHandle, // secure
+ kDestinationTypeSharedMemory, // non-secure
kDestinationTypeNativeHandle // secure
};
- virtual ssize_t decrypt(
- DestinationType dstType,
- const uint8_t key[16],
- const uint8_t iv[16],
- CryptoPlugin::Mode mode,
- const CryptoPlugin::Pattern &pattern,
- const sp<IMemory> &sharedBuffer, size_t offset,
+ struct DestinationBuffer {
+ DestinationType mType;
+ native_handle_t *mHandle;
+ sp<IMemory> mSharedMemory;
+ };
+
+ virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+ const sp<IMemory> &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- void *dstPtr,
- AString *errorDetailMsg) = 0;
+ const DestinationBuffer &destination, AString *errorDetailMsg) = 0;
private:
DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
diff --git a/include/media/PluginLoader.h b/include/media/PluginLoader.h
index 360af2d..a626e16 100644
--- a/include/media/PluginLoader.h
+++ b/include/media/PluginLoader.h
@@ -60,7 +60,10 @@
}
}
- T *getFactory(size_t i) const {return factories[i];}
+ T *getFactory(size_t i) const {
+ return factories[i];
+ }
+
size_t factoryCount() const {return factories.size();}
private:
@@ -74,12 +77,11 @@
CreateFactoryFunc createFactoryFunc =
(CreateFactoryFunc)library->lookup(entry);
if (createFactoryFunc) {
+ ALOGV("Found plugin factory entry %s in %s", entry, path);
libraries.push(library);
- return createFactoryFunc();
- } else {
- ALOGE("Failed to create plugin factory from %s at entry %s: %s",
- path, entry, library->lastError());
- }
+ T* result = createFactoryFunc();
+ return result;
+ }
}
return NULL;
}