1 /*
2 * Copyright (C) 2016 Team Kodi
3 * http://xbmc.org
4 *
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include "MediaDrm.h"
22 #include "MediaDrmOnEventListener.h"
23 #include "UUID.h"
24 #include "HashMap.h"
25
26 #include "jutils-details.hpp"
27
28 using namespace jni;
29
CJNIMediaDrm(const CJNIUUID & uuid)30 CJNIMediaDrm::CJNIMediaDrm(const CJNIUUID& uuid)
31 : CJNIBase("android/media/MediaDrm")
32 {
33 m_object = new_object(GetClassName(), "<init>", "(Ljava/util/UUID;)V",
34 uuid.get_raw());
35 m_object.setGlobal();
36 }
37
release() const38 void CJNIMediaDrm::release() const
39 {
40 call_method<void>(m_object,
41 "release", "()V");
42 }
43
openSession() const44 std::vector<char> CJNIMediaDrm::openSession() const
45 {
46 JNIEnv *env = xbmc_jnienv();
47 jhbyteArray array = call_method<jhbyteArray>(m_object,
48 "openSession", "()[B");
49
50 std::vector<char> result;
51
52 if (!env->ExceptionCheck())
53 {
54 jsize size = env->GetArrayLength(array.get());
55 result.resize(size);
56 env->GetByteArrayRegion(array.get(), 0, size, (jbyte*)result.data());
57 }
58
59 return result;
60 }
61
closeSession(const std::vector<char> & sessionId) const62 void CJNIMediaDrm::closeSession(const std::vector<char> & sessionId) const
63 {
64 JNIEnv *env = xbmc_jnienv();
65 call_method<void>(m_object,
66 "closeSession", "([B)V", jcast<jhbyteArray, std::vector<char> >(sessionId));
67 }
68
getPropertyString(const std::string & propertyName) const69 std::string CJNIMediaDrm::getPropertyString(const std::string &propertyName) const
70 {
71 return jcast<std::string>(call_method<jhstring>(m_object,
72 "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
73 jcast<jhstring>(propertyName)));
74 }
75
getPropertyByteArray(const std::string & propertyName) const76 std::vector<char> CJNIMediaDrm::getPropertyByteArray(const std::string &propertyName) const
77 {
78 JNIEnv *env = xbmc_jnienv();
79 jhbyteArray array = call_method<jhbyteArray>(m_object,
80 "getPropertyByteArray", "(Ljava/lang/String;)[B",
81 jcast<jhstring>(propertyName));
82
83 std::vector<char> result;
84
85 if (!env->ExceptionCheck())
86 {
87 jsize size = env->GetArrayLength(array.get());
88 result.resize(size);
89 env->GetByteArrayRegion(array.get(), 0, size, (jbyte*)result.data());
90 }
91 return result;
92 }
93
setPropertyString(const std::string & propertyName,const std::string & value) const94 void CJNIMediaDrm::setPropertyString(const std::string &propertyName, const std::string &value) const
95 {
96 call_method<void>(m_object,
97 "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
98 jcast<jhstring>(propertyName), jcast<jhstring>(value));
99 }
100
setPropertyByteArray(const std::string & propertyName,const std::vector<char> & value) const101 void CJNIMediaDrm::setPropertyByteArray(const std::string &propertyName, const std::vector<char> &value) const
102 {
103 JNIEnv *env = xbmc_jnienv();
104 call_method<void>(m_object,
105 "setPropertyByteArray", "(Ljava/lang/String;[B)V",
106 jcast<jhstring>(propertyName), jcast<jhbyteArray, std::vector<char> >(value));
107 }
108
getKeyRequest(const std::vector<char> & scope,const std::vector<char> & init,const std::string & mimeType,int keyType,const std::map<std::string,std::string> & optionalParameters) const109 CJNIMediaDrmKeyRequest CJNIMediaDrm::getKeyRequest(const std::vector<char> &scope,
110 const std::vector<char> &init, const std::string &mimeType, int keyType,
111 const std::map<std::string, std::string> &optionalParameters) const
112 {
113 JNIEnv *env = xbmc_jnienv();
114
115 CJNIHashMap hashMap;
116 for (const auto &item : optionalParameters)
117 hashMap.put(jcast<jhstring>(item.first), jcast<jhstring>(item.second));
118
119 CJNIMediaDrmKeyRequest result =
120 call_method<jhobject>(m_object,
121 "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)Landroid/media/MediaDrm$KeyRequest;",
122 jcast<jhbyteArray, std::vector<char> >(scope), jcast<jhbyteArray, std::vector<char> >(init),
123 jcast<jhstring>(mimeType), keyType, hashMap.get_raw());
124
125 return result;
126 }
127
provideKeyResponse(const std::vector<char> & scope,const std::vector<char> & response) const128 std::vector<char> CJNIMediaDrm::provideKeyResponse(const std::vector<char> &scope, const std::vector<char> &response) const
129 {
130 JNIEnv *env = xbmc_jnienv();
131 jhbyteArray array = call_method<jhbyteArray>(m_object,
132 "provideKeyResponse", "([B[B)[B", jcast<jhbyteArray, std::vector<char> >(scope),
133 jcast<jhbyteArray, std::vector<char> >(response));
134
135 std::vector<char> result;
136
137 if (!(!array))
138 {
139 jsize size = env->GetArrayLength(array.get());
140 result.resize(size);
141 env->GetByteArrayRegion(array.get(), 0, size, (jbyte*)result.data());
142 }
143 return result;
144 }
145
getProvisionRequest() const146 CJNIMediaDrmProvisionRequest CJNIMediaDrm::getProvisionRequest() const
147 {
148 return call_method<jhobject>(m_object,
149 "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;");
150 }
151
provideProvisionResponse(const std::vector<char> & response) const152 void CJNIMediaDrm::provideProvisionResponse(const std::vector<char> &response) const
153 {
154 call_method<void>(m_object,
155 "provideProvisionResponse", "([B)V", jcast<jhbyteArray, std::vector<char> >(response));
156 }
157
removeKeys(const std::vector<char> & sessionId) const158 void CJNIMediaDrm::removeKeys(const std::vector<char> &sessionId) const
159 {
160 call_method<void>(m_object,
161 "removeKeys", "([B)V", jcast<jhbyteArray, std::vector<char> >(sessionId));
162 }
163
setOnEventListener(const CJNIMediaDrmOnEventListener & listener) const164 void CJNIMediaDrm::setOnEventListener(const CJNIMediaDrmOnEventListener &listener) const
165 {
166 call_method<void>(m_object, "setOnEventListener",
167 "(Landroid/media/MediaDrm$OnEventListener;)V",
168 listener.get_raw());
169 }
170
queryKeyStatus(const std::vector<char> & sessionId) const171 std::map<std::string, std::string> CJNIMediaDrm::queryKeyStatus(const std::vector<char> &sessionId) const
172 {
173 if (CJNIBase::GetSDKVersion() >= 23)
174 {
175 std::map<std::string, std::string> result;
176
177 CJNIHashMap hashMap = call_method<jhobject>(m_object,
178 "queryKeyStatus", "([B)Ljava/util/HashMap;", jcast<jhbyteArray, std::vector<char> >(sessionId));
179 // Get a set with Map.entry from hashmap
180 jhobject entrySet = hashMap.entrySet();
181 // Get the Iterator
182 jhobject iterator = call_method<jhobject>(entrySet, "iterator", "()Ljava/util/Iterator;");
183 while (call_method<jboolean>(iterator, "hasNext", "()Z"))
184 {
185 jhobject next = call_method<jhobject>(iterator, "next", "()Ljava/util/Map$Entry;");
186 std::string key = jcast<std::string>(call_method<jhstring>(next, "getKey", "()Ljava/lang/Object;"));
187 std::string value = jcast<std::string>(call_method<jhstring>(next, "getValue", "()Ljava/lang/Object;"));
188 result[key] = value;
189 }
190 return result;
191 }
192 return std::map<std::string, std::string>();
193 }
194
getSecurityLevel(const std::vector<char> & sessionId) const195 int CJNIMediaDrm::getSecurityLevel(const std::vector<char> &sessionId) const
196 {
197 if (CJNIBase::GetSDKVersion() >= 28)
198 {
199 return call_method<int>(m_object,
200 "getSecurityLevel", "([B)I", jcast<jhbyteArray, std::vector<char> >(sessionId));
201 }
202 return -1;
203 }
204
205
getMaxSecurityLevel() const206 int CJNIMediaDrm::getMaxSecurityLevel() const
207 {
208 if (CJNIBase::GetSDKVersion() >= 28)
209 {
210 return call_static_method<int>(GetClassName().c_str(),
211 "getMaxSecurityLevel", "()I");
212 }
213 return -1;
214 }
215