xref: /aosp_15_r20/frameworks/rs/cpp/RenderScript.cpp (revision e1eccf28f96817838ad6867f7f39d2351ec11f56)
1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*e1eccf28SAndroid Build Coastguard Worker  *
4*e1eccf28SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e1eccf28SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e1eccf28SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e1eccf28SAndroid Build Coastguard Worker  *
8*e1eccf28SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e1eccf28SAndroid Build Coastguard Worker  *
10*e1eccf28SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e1eccf28SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e1eccf28SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1eccf28SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e1eccf28SAndroid Build Coastguard Worker  * limitations under the License.
15*e1eccf28SAndroid Build Coastguard Worker  */
16*e1eccf28SAndroid Build Coastguard Worker 
17*e1eccf28SAndroid Build Coastguard Worker #include <malloc.h>
18*e1eccf28SAndroid Build Coastguard Worker #include <string.h>
19*e1eccf28SAndroid Build Coastguard Worker #include <pthread.h>
20*e1eccf28SAndroid Build Coastguard Worker 
21*e1eccf28SAndroid Build Coastguard Worker #include "RenderScript.h"
22*e1eccf28SAndroid Build Coastguard Worker #include "rsCppStructs.h"
23*e1eccf28SAndroid Build Coastguard Worker #include "rsCppInternal.h"
24*e1eccf28SAndroid Build Coastguard Worker 
25*e1eccf28SAndroid Build Coastguard Worker #include <dlfcn.h>
26*e1eccf28SAndroid Build Coastguard Worker #include <unistd.h>
27*e1eccf28SAndroid Build Coastguard Worker 
28*e1eccf28SAndroid Build Coastguard Worker using android::RSC::RS;
29*e1eccf28SAndroid Build Coastguard Worker using android::RSC::RSError;
30*e1eccf28SAndroid Build Coastguard Worker 
31*e1eccf28SAndroid Build Coastguard Worker bool RS::gInitialized = false;
32*e1eccf28SAndroid Build Coastguard Worker bool RS::usingNative = false;
33*e1eccf28SAndroid Build Coastguard Worker pthread_mutex_t RS::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
34*e1eccf28SAndroid Build Coastguard Worker dispatchTable* RS::dispatch = nullptr;
35*e1eccf28SAndroid Build Coastguard Worker static int gInitError = 0;
36*e1eccf28SAndroid Build Coastguard Worker 
RS()37*e1eccf28SAndroid Build Coastguard Worker RS::RS() {
38*e1eccf28SAndroid Build Coastguard Worker     mContext = nullptr;
39*e1eccf28SAndroid Build Coastguard Worker     mErrorFunc = nullptr;
40*e1eccf28SAndroid Build Coastguard Worker     mMessageFunc = nullptr;
41*e1eccf28SAndroid Build Coastguard Worker     mMessageRun = false;
42*e1eccf28SAndroid Build Coastguard Worker     mInit = false;
43*e1eccf28SAndroid Build Coastguard Worker     mCurrentError = RS_SUCCESS;
44*e1eccf28SAndroid Build Coastguard Worker 
45*e1eccf28SAndroid Build Coastguard Worker     memset(&mElements, 0, sizeof(mElements));
46*e1eccf28SAndroid Build Coastguard Worker     memset(&mSamplers, 0, sizeof(mSamplers));
47*e1eccf28SAndroid Build Coastguard Worker }
48*e1eccf28SAndroid Build Coastguard Worker 
~RS()49*e1eccf28SAndroid Build Coastguard Worker RS::~RS() {
50*e1eccf28SAndroid Build Coastguard Worker     if (mInit == true) {
51*e1eccf28SAndroid Build Coastguard Worker         mMessageRun = false;
52*e1eccf28SAndroid Build Coastguard Worker 
53*e1eccf28SAndroid Build Coastguard Worker         if (mContext) {
54*e1eccf28SAndroid Build Coastguard Worker             finish();
55*e1eccf28SAndroid Build Coastguard Worker             RS::dispatch->ContextDeinitToClient(mContext);
56*e1eccf28SAndroid Build Coastguard Worker 
57*e1eccf28SAndroid Build Coastguard Worker             void *res = nullptr;
58*e1eccf28SAndroid Build Coastguard Worker             pthread_join(mMessageThreadId, &res);
59*e1eccf28SAndroid Build Coastguard Worker 
60*e1eccf28SAndroid Build Coastguard Worker             RS::dispatch->ContextDestroy(mContext);
61*e1eccf28SAndroid Build Coastguard Worker             mContext = nullptr;
62*e1eccf28SAndroid Build Coastguard Worker         }
63*e1eccf28SAndroid Build Coastguard Worker     }
64*e1eccf28SAndroid Build Coastguard Worker }
65*e1eccf28SAndroid Build Coastguard Worker 
init(const char * name,uint32_t flags)66*e1eccf28SAndroid Build Coastguard Worker bool RS::init(const char * name, uint32_t flags) {
67*e1eccf28SAndroid Build Coastguard Worker     return RS::init(name, flags, 0);
68*e1eccf28SAndroid Build Coastguard Worker }
69*e1eccf28SAndroid Build Coastguard Worker 
70*e1eccf28SAndroid Build Coastguard Worker // This will only open API 19+ libRS, because that's when
71*e1eccf28SAndroid Build Coastguard Worker // we changed libRS to extern "C" entry points.
loadSO(const char * filename,int targetApi)72*e1eccf28SAndroid Build Coastguard Worker static bool loadSO(const char* filename, int targetApi) {
73*e1eccf28SAndroid Build Coastguard Worker     void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
74*e1eccf28SAndroid Build Coastguard Worker     if (handle == nullptr) {
75*e1eccf28SAndroid Build Coastguard Worker         ALOGV("couldn't dlopen %s, %s", filename, dlerror());
76*e1eccf28SAndroid Build Coastguard Worker         return false;
77*e1eccf28SAndroid Build Coastguard Worker     }
78*e1eccf28SAndroid Build Coastguard Worker 
79*e1eccf28SAndroid Build Coastguard Worker     if (loadSymbols(handle, *RS::dispatch, targetApi) == false) {
80*e1eccf28SAndroid Build Coastguard Worker         ALOGV("%s init failed!", filename);
81*e1eccf28SAndroid Build Coastguard Worker         return false;
82*e1eccf28SAndroid Build Coastguard Worker     }
83*e1eccf28SAndroid Build Coastguard Worker     return true;
84*e1eccf28SAndroid Build Coastguard Worker }
85*e1eccf28SAndroid Build Coastguard Worker 
getProp(const char * str)86*e1eccf28SAndroid Build Coastguard Worker static uint32_t getProp(const char *str) {
87*e1eccf28SAndroid Build Coastguard Worker #if !defined(__LP64__) && defined(__ANDROID__)
88*e1eccf28SAndroid Build Coastguard Worker     char buf[256];
89*e1eccf28SAndroid Build Coastguard Worker     android::renderscript::property_get(str, buf, "0");
90*e1eccf28SAndroid Build Coastguard Worker     return atoi(buf);
91*e1eccf28SAndroid Build Coastguard Worker #else
92*e1eccf28SAndroid Build Coastguard Worker     return 0;
93*e1eccf28SAndroid Build Coastguard Worker #endif
94*e1eccf28SAndroid Build Coastguard Worker }
95*e1eccf28SAndroid Build Coastguard Worker 
initDispatch(int targetApi)96*e1eccf28SAndroid Build Coastguard Worker bool RS::initDispatch(int targetApi) {
97*e1eccf28SAndroid Build Coastguard Worker     pthread_mutex_lock(&gInitMutex);
98*e1eccf28SAndroid Build Coastguard Worker     if (gInitError) {
99*e1eccf28SAndroid Build Coastguard Worker         goto error;
100*e1eccf28SAndroid Build Coastguard Worker     } else if (gInitialized) {
101*e1eccf28SAndroid Build Coastguard Worker         pthread_mutex_unlock(&gInitMutex);
102*e1eccf28SAndroid Build Coastguard Worker         return true;
103*e1eccf28SAndroid Build Coastguard Worker     }
104*e1eccf28SAndroid Build Coastguard Worker 
105*e1eccf28SAndroid Build Coastguard Worker     RS::dispatch = new dispatchTable;
106*e1eccf28SAndroid Build Coastguard Worker 
107*e1eccf28SAndroid Build Coastguard Worker     // Attempt to load libRS, load libRSSupport on failure.
108*e1eccf28SAndroid Build Coastguard Worker     // If property is set, proceed directly to libRSSupport.
109*e1eccf28SAndroid Build Coastguard Worker     if (getProp("debug.rs.forcecompat") == 0) {
110*e1eccf28SAndroid Build Coastguard Worker         usingNative = loadSO("libRS.so", targetApi);
111*e1eccf28SAndroid Build Coastguard Worker     }
112*e1eccf28SAndroid Build Coastguard Worker     if (usingNative == false) {
113*e1eccf28SAndroid Build Coastguard Worker         if (loadSO("libRSSupport.so", targetApi) == false) {
114*e1eccf28SAndroid Build Coastguard Worker             ALOGE("Failed to load libRS.so and libRSSupport.so");
115*e1eccf28SAndroid Build Coastguard Worker             goto error;
116*e1eccf28SAndroid Build Coastguard Worker         }
117*e1eccf28SAndroid Build Coastguard Worker     }
118*e1eccf28SAndroid Build Coastguard Worker 
119*e1eccf28SAndroid Build Coastguard Worker     gInitialized = true;
120*e1eccf28SAndroid Build Coastguard Worker 
121*e1eccf28SAndroid Build Coastguard Worker     pthread_mutex_unlock(&gInitMutex);
122*e1eccf28SAndroid Build Coastguard Worker     return true;
123*e1eccf28SAndroid Build Coastguard Worker 
124*e1eccf28SAndroid Build Coastguard Worker  error:
125*e1eccf28SAndroid Build Coastguard Worker     gInitError = 1;
126*e1eccf28SAndroid Build Coastguard Worker     pthread_mutex_unlock(&gInitMutex);
127*e1eccf28SAndroid Build Coastguard Worker     return false;
128*e1eccf28SAndroid Build Coastguard Worker }
129*e1eccf28SAndroid Build Coastguard Worker 
init(const char * name,uint32_t flags,int targetApi)130*e1eccf28SAndroid Build Coastguard Worker bool RS::init(const char * name, uint32_t flags, int targetApi) {
131*e1eccf28SAndroid Build Coastguard Worker     if (mInit) {
132*e1eccf28SAndroid Build Coastguard Worker         return true;
133*e1eccf28SAndroid Build Coastguard Worker     }
134*e1eccf28SAndroid Build Coastguard Worker     // When using default value 0, set targetApi to RS_VERSION,
135*e1eccf28SAndroid Build Coastguard Worker     // to preserve the behavior of existing apps.
136*e1eccf28SAndroid Build Coastguard Worker     if (targetApi == 0) {
137*e1eccf28SAndroid Build Coastguard Worker         targetApi = RS_VERSION;
138*e1eccf28SAndroid Build Coastguard Worker     }
139*e1eccf28SAndroid Build Coastguard Worker 
140*e1eccf28SAndroid Build Coastguard Worker     if (initDispatch(targetApi) == false) {
141*e1eccf28SAndroid Build Coastguard Worker         ALOGE("Couldn't initialize dispatch table");
142*e1eccf28SAndroid Build Coastguard Worker         return false;
143*e1eccf28SAndroid Build Coastguard Worker     }
144*e1eccf28SAndroid Build Coastguard Worker 
145*e1eccf28SAndroid Build Coastguard Worker     uint32_t nameLen = strlen(name);
146*e1eccf28SAndroid Build Coastguard Worker     if (nameLen > PATH_MAX) {
147*e1eccf28SAndroid Build Coastguard Worker         ALOGE("The path to the cache directory is too long");
148*e1eccf28SAndroid Build Coastguard Worker         return false;
149*e1eccf28SAndroid Build Coastguard Worker     }
150*e1eccf28SAndroid Build Coastguard Worker     memcpy(mCacheDir, name, nameLen);
151*e1eccf28SAndroid Build Coastguard Worker     // Add the null character even if the user does not.
152*e1eccf28SAndroid Build Coastguard Worker     mCacheDir[nameLen] = 0;
153*e1eccf28SAndroid Build Coastguard Worker     mCacheDirLen = nameLen + 1;
154*e1eccf28SAndroid Build Coastguard Worker 
155*e1eccf28SAndroid Build Coastguard Worker     RsDevice device = RS::dispatch->DeviceCreate();
156*e1eccf28SAndroid Build Coastguard Worker     if (device == 0) {
157*e1eccf28SAndroid Build Coastguard Worker         ALOGE("Device creation failed");
158*e1eccf28SAndroid Build Coastguard Worker         return false;
159*e1eccf28SAndroid Build Coastguard Worker     }
160*e1eccf28SAndroid Build Coastguard Worker 
161*e1eccf28SAndroid Build Coastguard Worker     if (flags & ~(RS_CONTEXT_SYNCHRONOUS | RS_CONTEXT_LOW_LATENCY |
162*e1eccf28SAndroid Build Coastguard Worker                   RS_CONTEXT_LOW_POWER | RS_CONTEXT_WAIT_FOR_ATTACH)) {
163*e1eccf28SAndroid Build Coastguard Worker         ALOGE("Invalid flags passed");
164*e1eccf28SAndroid Build Coastguard Worker         return false;
165*e1eccf28SAndroid Build Coastguard Worker     }
166*e1eccf28SAndroid Build Coastguard Worker 
167*e1eccf28SAndroid Build Coastguard Worker     mContext = RS::dispatch->ContextCreate(device, 0, targetApi, RS_CONTEXT_TYPE_NORMAL, flags);
168*e1eccf28SAndroid Build Coastguard Worker     if (mContext == 0) {
169*e1eccf28SAndroid Build Coastguard Worker         ALOGE("Context creation failed");
170*e1eccf28SAndroid Build Coastguard Worker         return false;
171*e1eccf28SAndroid Build Coastguard Worker     }
172*e1eccf28SAndroid Build Coastguard Worker 
173*e1eccf28SAndroid Build Coastguard Worker     pid_t mNativeMessageThreadId;
174*e1eccf28SAndroid Build Coastguard Worker 
175*e1eccf28SAndroid Build Coastguard Worker     int status = pthread_create(&mMessageThreadId, nullptr, threadProc, this);
176*e1eccf28SAndroid Build Coastguard Worker     if (status) {
177*e1eccf28SAndroid Build Coastguard Worker         ALOGE("Failed to start RS message thread.");
178*e1eccf28SAndroid Build Coastguard Worker         return false;
179*e1eccf28SAndroid Build Coastguard Worker     }
180*e1eccf28SAndroid Build Coastguard Worker     // Wait for the message thread to be active.
181*e1eccf28SAndroid Build Coastguard Worker     while (!mMessageRun) {
182*e1eccf28SAndroid Build Coastguard Worker         usleep(1000);
183*e1eccf28SAndroid Build Coastguard Worker     }
184*e1eccf28SAndroid Build Coastguard Worker 
185*e1eccf28SAndroid Build Coastguard Worker     mInit = true;
186*e1eccf28SAndroid Build Coastguard Worker 
187*e1eccf28SAndroid Build Coastguard Worker     return true;
188*e1eccf28SAndroid Build Coastguard Worker }
189*e1eccf28SAndroid Build Coastguard Worker 
throwError(RSError error,const char * errMsg)190*e1eccf28SAndroid Build Coastguard Worker void RS::throwError(RSError error, const char *errMsg) {
191*e1eccf28SAndroid Build Coastguard Worker     if (mCurrentError == RS_SUCCESS) {
192*e1eccf28SAndroid Build Coastguard Worker         mCurrentError = error;
193*e1eccf28SAndroid Build Coastguard Worker         ALOGE("RS CPP error: %s", errMsg);
194*e1eccf28SAndroid Build Coastguard Worker     } else {
195*e1eccf28SAndroid Build Coastguard Worker         ALOGE("RS CPP error (masked by previous error): %s", errMsg);
196*e1eccf28SAndroid Build Coastguard Worker     }
197*e1eccf28SAndroid Build Coastguard Worker }
198*e1eccf28SAndroid Build Coastguard Worker 
getError()199*e1eccf28SAndroid Build Coastguard Worker RSError RS::getError() {
200*e1eccf28SAndroid Build Coastguard Worker     return mCurrentError;
201*e1eccf28SAndroid Build Coastguard Worker }
202*e1eccf28SAndroid Build Coastguard Worker 
203*e1eccf28SAndroid Build Coastguard Worker 
threadProc(void * vrsc)204*e1eccf28SAndroid Build Coastguard Worker void * RS::threadProc(void *vrsc) {
205*e1eccf28SAndroid Build Coastguard Worker     RS *rs = static_cast<RS *>(vrsc);
206*e1eccf28SAndroid Build Coastguard Worker     size_t rbuf_size = 256;
207*e1eccf28SAndroid Build Coastguard Worker     void * rbuf = malloc(rbuf_size);
208*e1eccf28SAndroid Build Coastguard Worker 
209*e1eccf28SAndroid Build Coastguard Worker     RS::dispatch->ContextInitToClient(rs->mContext);
210*e1eccf28SAndroid Build Coastguard Worker     rs->mMessageRun = true;
211*e1eccf28SAndroid Build Coastguard Worker 
212*e1eccf28SAndroid Build Coastguard Worker     while (rs->mMessageRun) {
213*e1eccf28SAndroid Build Coastguard Worker         size_t receiveLen = 0;
214*e1eccf28SAndroid Build Coastguard Worker         uint32_t usrID = 0;
215*e1eccf28SAndroid Build Coastguard Worker         uint32_t subID = 0;
216*e1eccf28SAndroid Build Coastguard Worker         RsMessageToClientType r = RS::dispatch->ContextPeekMessage(rs->mContext,
217*e1eccf28SAndroid Build Coastguard Worker                                                                    &receiveLen, sizeof(receiveLen),
218*e1eccf28SAndroid Build Coastguard Worker                                                                    &usrID, sizeof(usrID));
219*e1eccf28SAndroid Build Coastguard Worker 
220*e1eccf28SAndroid Build Coastguard Worker         if (receiveLen >= rbuf_size) {
221*e1eccf28SAndroid Build Coastguard Worker             rbuf_size = receiveLen + 32;
222*e1eccf28SAndroid Build Coastguard Worker             void *tmpBuf = realloc(rbuf, rbuf_size);
223*e1eccf28SAndroid Build Coastguard Worker             if (tmpBuf) {
224*e1eccf28SAndroid Build Coastguard Worker                 rbuf = tmpBuf;
225*e1eccf28SAndroid Build Coastguard Worker             } else {
226*e1eccf28SAndroid Build Coastguard Worker                 free(rbuf);
227*e1eccf28SAndroid Build Coastguard Worker                 rbuf = NULL;
228*e1eccf28SAndroid Build Coastguard Worker             }
229*e1eccf28SAndroid Build Coastguard Worker         }
230*e1eccf28SAndroid Build Coastguard Worker         if (!rbuf) {
231*e1eccf28SAndroid Build Coastguard Worker             ALOGE("RS::message handler realloc error %zu", rbuf_size);
232*e1eccf28SAndroid Build Coastguard Worker             // No clean way to recover now?
233*e1eccf28SAndroid Build Coastguard Worker         }
234*e1eccf28SAndroid Build Coastguard Worker         RS::dispatch->ContextGetMessage(rs->mContext, rbuf, rbuf_size, &receiveLen, sizeof(receiveLen),
235*e1eccf28SAndroid Build Coastguard Worker                             &subID, sizeof(subID));
236*e1eccf28SAndroid Build Coastguard Worker 
237*e1eccf28SAndroid Build Coastguard Worker         switch(r) {
238*e1eccf28SAndroid Build Coastguard Worker         case RS_MESSAGE_TO_CLIENT_ERROR:
239*e1eccf28SAndroid Build Coastguard Worker             ALOGE("RS Error %s", (const char *)rbuf);
240*e1eccf28SAndroid Build Coastguard Worker             rs->throwError(RS_ERROR_RUNTIME_ERROR, "Error returned from runtime");
241*e1eccf28SAndroid Build Coastguard Worker             if(rs->mMessageFunc != nullptr) {
242*e1eccf28SAndroid Build Coastguard Worker                 rs->mErrorFunc(usrID, (const char *)rbuf);
243*e1eccf28SAndroid Build Coastguard Worker             }
244*e1eccf28SAndroid Build Coastguard Worker             break;
245*e1eccf28SAndroid Build Coastguard Worker         case RS_MESSAGE_TO_CLIENT_NONE:
246*e1eccf28SAndroid Build Coastguard Worker         case RS_MESSAGE_TO_CLIENT_EXCEPTION:
247*e1eccf28SAndroid Build Coastguard Worker         case RS_MESSAGE_TO_CLIENT_RESIZE:
248*e1eccf28SAndroid Build Coastguard Worker             /*
249*e1eccf28SAndroid Build Coastguard Worker              * Teardown. We want to avoid starving other threads during
250*e1eccf28SAndroid Build Coastguard Worker              * teardown by yielding until the next line in the destructor can
251*e1eccf28SAndroid Build Coastguard Worker              * execute to set mRun = false. Note that the FIFO sends an
252*e1eccf28SAndroid Build Coastguard Worker              * empty NONE message when it reaches its destructor.
253*e1eccf28SAndroid Build Coastguard Worker              */
254*e1eccf28SAndroid Build Coastguard Worker             usleep(1000);
255*e1eccf28SAndroid Build Coastguard Worker             break;
256*e1eccf28SAndroid Build Coastguard Worker         case RS_MESSAGE_TO_CLIENT_USER:
257*e1eccf28SAndroid Build Coastguard Worker             if(rs->mMessageFunc != nullptr) {
258*e1eccf28SAndroid Build Coastguard Worker                 rs->mMessageFunc(usrID, rbuf, receiveLen);
259*e1eccf28SAndroid Build Coastguard Worker             } else {
260*e1eccf28SAndroid Build Coastguard Worker                 ALOGE("Received a message from the script with no message handler installed.");
261*e1eccf28SAndroid Build Coastguard Worker             }
262*e1eccf28SAndroid Build Coastguard Worker             break;
263*e1eccf28SAndroid Build Coastguard Worker 
264*e1eccf28SAndroid Build Coastguard Worker         default:
265*e1eccf28SAndroid Build Coastguard Worker             ALOGE("RS unknown message type %i", r);
266*e1eccf28SAndroid Build Coastguard Worker         }
267*e1eccf28SAndroid Build Coastguard Worker     }
268*e1eccf28SAndroid Build Coastguard Worker 
269*e1eccf28SAndroid Build Coastguard Worker     if (rbuf) {
270*e1eccf28SAndroid Build Coastguard Worker         free(rbuf);
271*e1eccf28SAndroid Build Coastguard Worker     }
272*e1eccf28SAndroid Build Coastguard Worker     ALOGV("RS Message thread exiting.");
273*e1eccf28SAndroid Build Coastguard Worker     return nullptr;
274*e1eccf28SAndroid Build Coastguard Worker }
275*e1eccf28SAndroid Build Coastguard Worker 
setErrorHandler(ErrorHandlerFunc_t func)276*e1eccf28SAndroid Build Coastguard Worker void RS::setErrorHandler(ErrorHandlerFunc_t func) {
277*e1eccf28SAndroid Build Coastguard Worker     mErrorFunc = func;
278*e1eccf28SAndroid Build Coastguard Worker }
279*e1eccf28SAndroid Build Coastguard Worker 
setMessageHandler(MessageHandlerFunc_t func)280*e1eccf28SAndroid Build Coastguard Worker void RS::setMessageHandler(MessageHandlerFunc_t func) {
281*e1eccf28SAndroid Build Coastguard Worker     mMessageFunc  = func;
282*e1eccf28SAndroid Build Coastguard Worker }
283*e1eccf28SAndroid Build Coastguard Worker 
finish()284*e1eccf28SAndroid Build Coastguard Worker void RS::finish() {
285*e1eccf28SAndroid Build Coastguard Worker     RS::dispatch->ContextFinish(mContext);
286*e1eccf28SAndroid Build Coastguard Worker }
287