1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  icensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "[email protected]"
19 
20 #include <android/hardware/cas/1.1/ICasListener.h>
21 #include <android/hardware/cas/1.2/ICasListener.h>
22 #include <media/cas/CasAPI.h>
23 #include <utils/Log.h>
24 
25 #include "CasImpl.h"
26 #include "SharedLibrary.h"
27 #include "TypeConvert.h"
28 
29 namespace android {
30 namespace hardware {
31 namespace cas {
32 namespace V1_1 {
33 namespace implementation {
34 
CasImpl(const sp<ICasListener> & listener)35 CasImpl::CasImpl(const sp<ICasListener>& listener) : mListener(listener) {
36     ALOGV("CTOR");
37 }
38 
~CasImpl()39 CasImpl::~CasImpl() {
40     ALOGV("DTOR");
41     release();
42 }
43 
44 // static
OnEvent(void * appData,int32_t event,int32_t arg,uint8_t * data,size_t size)45 void CasImpl::OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size) {
46     if (appData == NULL) {
47         ALOGE("Invalid appData!");
48         return;
49     }
50     CasImpl* casImpl = static_cast<CasImpl*>(appData);
51     casImpl->onEvent(event, arg, data, size);
52 }
53 
54 // static
CallBackExt(void * appData,int32_t event,int32_t arg,uint8_t * data,size_t size,const CasSessionId * sessionId)55 void CasImpl::CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size,
56                           const CasSessionId* sessionId) {
57     if (appData == NULL) {
58         ALOGE("Invalid appData!");
59         return;
60     }
61     CasImpl* casImpl = static_cast<CasImpl*>(appData);
62     casImpl->onEvent(sessionId, event, arg, data, size);
63 }
64 
65 // static
StatusUpdate(void * appData,int32_t event,int32_t arg)66 void CasImpl::StatusUpdate(void* appData, int32_t event, int32_t arg) {
67     if (appData == NULL) {
68         ALOGE("Invalid appData!");
69         return;
70     }
71     CasImpl* casImpl = static_cast<CasImpl*>(appData);
72     casImpl->onStatusUpdate(event, arg);
73 }
74 
init(const sp<SharedLibrary> & library,CasPlugin * plugin)75 void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin* plugin) {
76     mLibrary = library;
77     std::shared_ptr<CasPlugin> holder(plugin);
78     std::atomic_store(&mPluginHolder, holder);
79 }
80 
onEvent(int32_t event,int32_t arg,uint8_t * data,size_t size)81 void CasImpl::onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size) {
82     if (mListener == NULL) {
83         return;
84     }
85 
86     HidlCasData eventData;
87     if (data != NULL) {
88         eventData.setToExternal(data, size);
89     }
90 
91     mListener->onEvent(event, arg, eventData);
92 }
93 
onEvent(const CasSessionId * sessionId,int32_t event,int32_t arg,uint8_t * data,size_t size)94 void CasImpl::onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data,
95                       size_t size) {
96     if (mListener == NULL) {
97         return;
98     }
99 
100     HidlCasData eventData;
101     if (data != NULL) {
102         eventData.setToExternal(data, size);
103     }
104 
105     if (sessionId != NULL) {
106         mListener->onSessionEvent(*sessionId, event, arg, eventData);
107     } else {
108         mListener->onEvent(event, arg, eventData);
109     }
110 }
111 
onStatusUpdate(int32_t event,int32_t arg)112 void CasImpl::onStatusUpdate(int32_t event, int32_t arg) {
113     if (mListener == NULL) {
114         return;
115     }
116     sp<V1_2::ICasListener> listenerV1_2 = V1_2::ICasListener::castFrom(mListener);
117 
118     if (listenerV1_2 != NULL) {
119         listenerV1_2->onStatusUpdate(static_cast<StatusEvent>(event), arg);
120     }
121 }
122 
setPluginStatusUpdateCallback()123 Return<Status> CasImpl::setPluginStatusUpdateCallback() {
124     ALOGV("%s", __FUNCTION__);
125     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
126     if (holder.get() == nullptr) {
127         return toStatus(INVALID_OPERATION);
128     }
129     return toStatus(holder->setStatusCallback(&CasImpl::StatusUpdate));
130 }
131 
setPrivateData(const HidlCasData & pvtData)132 Return<Status> CasImpl::setPrivateData(const HidlCasData& pvtData) {
133     ALOGV("%s", __FUNCTION__);
134     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
135     if (holder.get() == nullptr) {
136         return toStatus(INVALID_OPERATION);
137     }
138     return toStatus(holder->setPrivateData(pvtData));
139 }
140 
openSession(openSession_cb _hidl_cb)141 Return<void> CasImpl::openSession(openSession_cb _hidl_cb) {
142     ALOGV("%s", __FUNCTION__);
143     CasSessionId sessionId;
144 
145     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
146     status_t err = INVALID_OPERATION;
147     if (holder.get() != nullptr) {
148         err = holder->openSession(&sessionId);
149         holder.reset();
150     }
151 
152     _hidl_cb(toStatus(err), sessionId);
153 
154     return Void();
155 }
156 
openSession_1_2(const SessionIntent intent,const ScramblingMode mode,openSession_1_2_cb _hidl_cb)157 Return<void> CasImpl::openSession_1_2(const SessionIntent intent, const ScramblingMode mode,
158                                       openSession_1_2_cb _hidl_cb) {
159     ALOGV("%s", __FUNCTION__);
160     CasSessionId sessionId;
161 
162     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
163     status_t err = INVALID_OPERATION;
164     if (holder.get() != nullptr) {
165         err = holder->openSession(static_cast<uint32_t>(intent), static_cast<uint32_t>(mode),
166                                   &sessionId);
167         holder.reset();
168     }
169 
170     _hidl_cb(toStatus_1_2(err), sessionId);
171 
172     return Void();
173 }
174 
setSessionPrivateData(const HidlCasSessionId & sessionId,const HidlCasData & pvtData)175 Return<Status> CasImpl::setSessionPrivateData(const HidlCasSessionId& sessionId,
176                                               const HidlCasData& pvtData) {
177     ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
178     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
179     if (holder.get() == nullptr) {
180         return toStatus(INVALID_OPERATION);
181     }
182     return toStatus(holder->setSessionPrivateData(sessionId, pvtData));
183 }
184 
closeSession(const HidlCasSessionId & sessionId)185 Return<Status> CasImpl::closeSession(const HidlCasSessionId& sessionId) {
186     ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
187     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
188     if (holder.get() == nullptr) {
189         return toStatus(INVALID_OPERATION);
190     }
191     return toStatus(holder->closeSession(sessionId));
192 }
193 
processEcm(const HidlCasSessionId & sessionId,const HidlCasData & ecm)194 Return<Status> CasImpl::processEcm(const HidlCasSessionId& sessionId, const HidlCasData& ecm) {
195     ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
196     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
197     if (holder.get() == nullptr) {
198         return toStatus(INVALID_OPERATION);
199     }
200 
201     return toStatus(holder->processEcm(sessionId, ecm));
202 }
203 
processEmm(const HidlCasData & emm)204 Return<Status> CasImpl::processEmm(const HidlCasData& emm) {
205     ALOGV("%s", __FUNCTION__);
206     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
207     if (holder.get() == nullptr) {
208         return toStatus(INVALID_OPERATION);
209     }
210 
211     return toStatus(holder->processEmm(emm));
212 }
213 
sendEvent(int32_t event,int32_t arg,const HidlCasData & eventData)214 Return<Status> CasImpl::sendEvent(int32_t event, int32_t arg, const HidlCasData& eventData) {
215     ALOGV("%s", __FUNCTION__);
216     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
217     if (holder.get() == nullptr) {
218         return toStatus(INVALID_OPERATION);
219     }
220 
221     status_t err = holder->sendEvent(event, arg, eventData);
222     return toStatus(err);
223 }
224 
sendSessionEvent(const HidlCasSessionId & sessionId,int32_t event,int32_t arg,const HidlCasData & eventData)225 Return<Status> CasImpl::sendSessionEvent(const HidlCasSessionId& sessionId, int32_t event,
226                                          int32_t arg, const HidlCasData& eventData) {
227     ALOGV("%s", __FUNCTION__);
228     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
229     if (holder.get() == nullptr) {
230         return toStatus(INVALID_OPERATION);
231     }
232 
233     status_t err = holder->sendSessionEvent(sessionId, event, arg, eventData);
234     return toStatus(err);
235 }
236 
provision(const hidl_string & provisionString)237 Return<Status> CasImpl::provision(const hidl_string& provisionString) {
238     ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str());
239     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
240     if (holder.get() == nullptr) {
241         return toStatus(INVALID_OPERATION);
242     }
243 
244     return toStatus(holder->provision(String8(provisionString.c_str())));
245 }
246 
refreshEntitlements(int32_t refreshType,const HidlCasData & refreshData)247 Return<Status> CasImpl::refreshEntitlements(int32_t refreshType, const HidlCasData& refreshData) {
248     ALOGV("%s", __FUNCTION__);
249     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
250     if (holder.get() == nullptr) {
251         return toStatus(INVALID_OPERATION);
252     }
253 
254     status_t err = holder->refreshEntitlements(refreshType, refreshData);
255     return toStatus(err);
256 }
257 
release()258 Return<Status> CasImpl::release() {
259     ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get());
260 
261     std::shared_ptr<CasPlugin> holder(nullptr);
262     std::atomic_store(&mPluginHolder, holder);
263 
264     return Status::OK;
265 }
266 
267 }  // namespace implementation
268 }  // namespace V1_1
269 }  // namespace cas
270 }  // namespace hardware
271 }  // namespace android
272