1221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams/*
2a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray * Copyright (C) 2013 The Android Open Source Project
3221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams *
4221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams * you may not use this file except in compliance with the License.
6221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams * You may obtain a copy of the License at
7221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams *
8221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams *
10221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams * Unless required by applicable law or agreed to in writing, software
11221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams * See the License for the specific language governing permissions and
14221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams * limitations under the License.
15221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams */
16221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
17221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams#include <malloc.h>
18221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams#include <string.h>
1984bf2b877024aaa154b66e0f2338d54bdabd855aTim Murray#include <pthread.h>
20221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
21221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams#include "RenderScript.h"
2289daad6bae798779e57f252e9da4fe4e62337124Tim Murray#include "rsCppStructs.h"
23eeaf7142d7e06efb3e0ddc7ef542884ab1d527dcTim Murray#include "rsCppInternal.h"
24221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
25a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray#include <dlfcn.h>
260f98d50a8128e68760aa6e819b962e9a1d4b5bedTim Murray#include <unistd.h>
27a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray
28dfcfabfccad8a8f2f42f83081638c7e5c9bfb4b9Chih-Hung Hsiehusing android::RSC::RS;
29dfcfabfccad8a8f2f42f83081638c7e5c9bfb4b9Chih-Hung Hsiehusing android::RSC::RSError;
3069cccdf0659a193d6a75420ec745421fb5c436e6Jason Sams
3184bf2b877024aaa154b66e0f2338d54bdabd855aTim Murraybool RS::gInitialized = false;
324a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murraybool RS::usingNative = false;
3384bf2b877024aaa154b66e0f2338d54bdabd855aTim Murraypthread_mutex_t RS::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
3444bef6fba6244292b751387f3d6c31cca96c28adChris WailesdispatchTable* RS::dispatch = nullptr;
35a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murraystatic int gInitError = 0;
36221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
3784bf2b877024aaa154b66e0f2338d54bdabd855aTim MurrayRS::RS() {
3844bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mContext = nullptr;
3944bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mErrorFunc = nullptr;
4044bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mMessageFunc = nullptr;
41221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    mMessageRun = false;
42a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    mInit = false;
4321fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murray    mCurrentError = RS_SUCCESS;
44221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
45221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    memset(&mElements, 0, sizeof(mElements));
46729b6fe58aff47c4f666b22bbb7a6d6114ddefa9Tim Murray    memset(&mSamplers, 0, sizeof(mSamplers));
47221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams}
48221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
4984bf2b877024aaa154b66e0f2338d54bdabd855aTim MurrayRS::~RS() {
50a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    if (mInit == true) {
51a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray        mMessageRun = false;
52221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
53fea96e8d145b1915b7bd66f68e973dd572a469e3Xiaofei Wan        if (mContext) {
54e8f9651ed5678846959771bc32a310674408e8a8Miao Wang            finish();
55fea96e8d145b1915b7bd66f68e973dd572a469e3Xiaofei Wan            RS::dispatch->ContextDeinitToClient(mContext);
56fea96e8d145b1915b7bd66f68e973dd572a469e3Xiaofei Wan
5744bef6fba6244292b751387f3d6c31cca96c28adChris Wailes            void *res = nullptr;
58c2459dc5f1c9d299247f77d565c5be5dc57c75e0Yang Ni            pthread_join(mMessageThreadId, &res);
59fea96e8d145b1915b7bd66f68e973dd572a469e3Xiaofei Wan
60fea96e8d145b1915b7bd66f68e973dd572a469e3Xiaofei Wan            RS::dispatch->ContextDestroy(mContext);
6144bef6fba6244292b751387f3d6c31cca96c28adChris Wailes            mContext = nullptr;
62fea96e8d145b1915b7bd66f68e973dd572a469e3Xiaofei Wan        }
63a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    }
64221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams}
65221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
66fda559674cb1bd16b885f97951bda775cdc3af5cMiao Wangbool RS::init(const char * name, uint32_t flags) {
67fda559674cb1bd16b885f97951bda775cdc3af5cMiao Wang    return RS::init(name, flags, 0);
68fda559674cb1bd16b885f97951bda775cdc3af5cMiao Wang}
69fda559674cb1bd16b885f97951bda775cdc3af5cMiao Wang
70cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang// This will only open API 19+ libRS, because that's when
71cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang// we changed libRS to extern "C" entry points.
72e5428e661ce6f9d24f838cab0a8fb0fa8c76dbcaMiao Wangstatic bool loadSO(const char* filename, int targetApi) {
734a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
7444bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    if (handle == nullptr) {
7587c9d77a3be0dff4a4413bbb6f5b91014896e048Tim Murray        ALOGV("couldn't dlopen %s, %s", filename, dlerror());
764a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray        return false;
774a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    }
780b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray
79e5428e661ce6f9d24f838cab0a8fb0fa8c76dbcaMiao Wang    if (loadSymbols(handle, *RS::dispatch, targetApi) == false) {
8087c9d77a3be0dff4a4413bbb6f5b91014896e048Tim Murray        ALOGV("%s init failed!", filename);
814a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray        return false;
824a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    }
834a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    return true;
844a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray}
854a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray
864a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murraystatic uint32_t getProp(const char *str) {
8762237219e567b9f972c86e7ca4e96f9b3d5ad4deMiao Wang#if !defined(__LP64__) && defined(__ANDROID__)
884a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    char buf[256];
892a61168a777ee434ce2c28945aa74f6a6bcf2820Miao Wang    android::renderscript::property_get(str, buf, "0");
904a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    return atoi(buf);
914a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray#else
924a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    return 0;
934a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray#endif
944a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray}
954a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray
964a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murraybool RS::initDispatch(int targetApi) {
970b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray    pthread_mutex_lock(&gInitMutex);
980b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray    if (gInitError) {
990b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray        goto error;
1000b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray    } else if (gInitialized) {
10147666f52468d8ce14498fac635125f24f79d3257Tim Murray        pthread_mutex_unlock(&gInitMutex);
1020b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray        return true;
1030b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray    }
1040b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray
1050b8a2be7eb9322ec221383de325be8f30b36fe9aTim Murray    RS::dispatch = new dispatchTable;
1064a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray
107cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang    // Attempt to load libRS, load libRSSupport on failure.
108cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang    // If property is set, proceed directly to libRSSupport.
1094a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    if (getProp("debug.rs.forcecompat") == 0) {
110e5428e661ce6f9d24f838cab0a8fb0fa8c76dbcaMiao Wang        usingNative = loadSO("libRS.so", targetApi);
1114a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    }
1124a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray    if (usingNative == false) {
113e5428e661ce6f9d24f838cab0a8fb0fa8c76dbcaMiao Wang        if (loadSO("libRSSupport.so", targetApi) == false) {
1144a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray            ALOGE("Failed to load libRS.so and libRSSupport.so");
1154a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray            goto error;
1164a92d1268983edaf329f73c8a5b8860cdbb11596Tim Murray        }
117a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    }
118a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray
119a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    gInitialized = true;
120a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray
121a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    pthread_mutex_unlock(&gInitMutex);
122a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    return true;
123a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray
124a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray error:
125a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    gInitError = 1;
126a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    pthread_mutex_unlock(&gInitMutex);
127a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    return false;
128a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray}
129a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray
130d9a0257f82cf4c634f6d2005c7fe1b46b1f7e1f1Miao Wangbool RS::init(const char * name, uint32_t flags, int targetApi) {
131caf4126512b2152ea5f6573ce5d9ca29767b9678Tim Murray    if (mInit) {
132caf4126512b2152ea5f6573ce5d9ca29767b9678Tim Murray        return true;
133caf4126512b2152ea5f6573ce5d9ca29767b9678Tim Murray    }
134d9a0257f82cf4c634f6d2005c7fe1b46b1f7e1f1Miao Wang    // When using default value 0, set targetApi to RS_VERSION,
135d9a0257f82cf4c634f6d2005c7fe1b46b1f7e1f1Miao Wang    // to preserve the behavior of existing apps.
136d9a0257f82cf4c634f6d2005c7fe1b46b1f7e1f1Miao Wang    if (targetApi == 0) {
137d9a0257f82cf4c634f6d2005c7fe1b46b1f7e1f1Miao Wang        targetApi = RS_VERSION;
138d9a0257f82cf4c634f6d2005c7fe1b46b1f7e1f1Miao Wang    }
139caf4126512b2152ea5f6573ce5d9ca29767b9678Tim Murray
140a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    if (initDispatch(targetApi) == false) {
141a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray        ALOGE("Couldn't initialize dispatch table");
142a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray        return false;
143a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    }
144a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray
145bc10dff26207bb8c02051b28326bb134a8f28eb3Miao Wang    uint32_t nameLen = strlen(name);
146bc10dff26207bb8c02051b28326bb134a8f28eb3Miao Wang    if (nameLen > PATH_MAX) {
147bc10dff26207bb8c02051b28326bb134a8f28eb3Miao Wang        ALOGE("The path to the cache directory is too long");
148bc10dff26207bb8c02051b28326bb134a8f28eb3Miao Wang        return false;
149bc10dff26207bb8c02051b28326bb134a8f28eb3Miao Wang    }
150bc10dff26207bb8c02051b28326bb134a8f28eb3Miao Wang    memcpy(mCacheDir, name, nameLen);
151cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang    // Add the null character even if the user does not.
152cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang    mCacheDir[nameLen] = 0;
153bc10dff26207bb8c02051b28326bb134a8f28eb3Miao Wang    mCacheDirLen = nameLen + 1;
154caf4126512b2152ea5f6573ce5d9ca29767b9678Tim Murray
1558ca49acfcc784355bd806f87701747a4c1ab9749Yang Ni    RsDevice device = RS::dispatch->DeviceCreate();
1568ca49acfcc784355bd806f87701747a4c1ab9749Yang Ni    if (device == 0) {
157221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        ALOGE("Device creation failed");
158221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        return false;
159221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    }
160221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
161bfa5a8e76fd9469cdecb3115685ded677d2d210aJason Sams    if (flags & ~(RS_CONTEXT_SYNCHRONOUS | RS_CONTEXT_LOW_LATENCY |
16215c1d06c654c246b8e8047f64f781add32483576Stephen McGroarty                  RS_CONTEXT_LOW_POWER | RS_CONTEXT_WAIT_FOR_ATTACH)) {
16384e3dea053bea25c1cec44ffb298f8b5b9b9141aTim Murray        ALOGE("Invalid flags passed");
16484e3dea053bea25c1cec44ffb298f8b5b9b9141aTim Murray        return false;
16584e3dea053bea25c1cec44ffb298f8b5b9b9141aTim Murray    }
16684e3dea053bea25c1cec44ffb298f8b5b9b9141aTim Murray
1678ca49acfcc784355bd806f87701747a4c1ab9749Yang Ni    mContext = RS::dispatch->ContextCreate(device, 0, targetApi, RS_CONTEXT_TYPE_NORMAL, flags);
168221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    if (mContext == 0) {
169221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        ALOGE("Context creation failed");
170221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        return false;
171221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    }
172221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
173221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    pid_t mNativeMessageThreadId;
174221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
17544bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    int status = pthread_create(&mMessageThreadId, nullptr, threadProc, this);
176221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    if (status) {
17784bf2b877024aaa154b66e0f2338d54bdabd855aTim Murray        ALOGE("Failed to start RS message thread.");
178221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        return false;
179221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    }
180221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    // Wait for the message thread to be active.
181221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    while (!mMessageRun) {
182221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        usleep(1000);
183221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    }
184221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
185a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    mInit = true;
186a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray
187221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    return true;
188221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams}
189221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
19021fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murrayvoid RS::throwError(RSError error, const char *errMsg) {
19121fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murray    if (mCurrentError == RS_SUCCESS) {
19221fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murray        mCurrentError = error;
19321fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murray        ALOGE("RS CPP error: %s", errMsg);
19421fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murray    } else {
19521fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murray        ALOGE("RS CPP error (masked by previous error): %s", errMsg);
19621fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murray    }
197b2e3dc51dcbbe52b5e72d9c6a16de7000de70edfJason Sams}
198b2e3dc51dcbbe52b5e72d9c6a16de7000de70edfJason Sams
19910913a5c37ba119bef335320d3e8be25212c05adTim MurrayRSError RS::getError() {
20010913a5c37ba119bef335320d3e8be25212c05adTim Murray    return mCurrentError;
20110913a5c37ba119bef335320d3e8be25212c05adTim Murray}
20210913a5c37ba119bef335320d3e8be25212c05adTim Murray
203b2e3dc51dcbbe52b5e72d9c6a16de7000de70edfJason Sams
20484bf2b877024aaa154b66e0f2338d54bdabd855aTim Murrayvoid * RS::threadProc(void *vrsc) {
20584bf2b877024aaa154b66e0f2338d54bdabd855aTim Murray    RS *rs = static_cast<RS *>(vrsc);
206221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    size_t rbuf_size = 256;
207221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    void * rbuf = malloc(rbuf_size);
208221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
209a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    RS::dispatch->ContextInitToClient(rs->mContext);
210221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    rs->mMessageRun = true;
211221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
212221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    while (rs->mMessageRun) {
213221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        size_t receiveLen = 0;
214221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        uint32_t usrID = 0;
215221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        uint32_t subID = 0;
216a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray        RsMessageToClientType r = RS::dispatch->ContextPeekMessage(rs->mContext,
217a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray                                                                   &receiveLen, sizeof(receiveLen),
218a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray                                                                   &usrID, sizeof(usrID));
219221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
220221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        if (receiveLen >= rbuf_size) {
221221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            rbuf_size = receiveLen + 32;
222221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            rbuf = realloc(rbuf, rbuf_size);
223221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        }
224221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        if (!rbuf) {
22584bf2b877024aaa154b66e0f2338d54bdabd855aTim Murray            ALOGE("RS::message handler realloc error %zu", rbuf_size);
226221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            // No clean way to recover now?
227221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        }
228a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray        RS::dispatch->ContextGetMessage(rs->mContext, rbuf, rbuf_size, &receiveLen, sizeof(receiveLen),
229221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams                            &subID, sizeof(subID));
230221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
231221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        switch(r) {
232221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        case RS_MESSAGE_TO_CLIENT_ERROR:
233221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            ALOGE("RS Error %s", (const char *)rbuf);
23421fa7a0a23eddab88ff261017f6d7a2548b4d89aTim Murray            rs->throwError(RS_ERROR_RUNTIME_ERROR, "Error returned from runtime");
23544bef6fba6244292b751387f3d6c31cca96c28adChris Wailes            if(rs->mMessageFunc != nullptr) {
236221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams                rs->mErrorFunc(usrID, (const char *)rbuf);
237221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            }
238221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            break;
23976a1be4a35267cf0814fb85fb9b1b5bf887e6ae7Stephen Hines        case RS_MESSAGE_TO_CLIENT_NONE:
240221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        case RS_MESSAGE_TO_CLIENT_EXCEPTION:
24176a1be4a35267cf0814fb85fb9b1b5bf887e6ae7Stephen Hines        case RS_MESSAGE_TO_CLIENT_RESIZE:
242cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang            /*
243cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang             * Teardown. We want to avoid starving other threads during
244cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang             * teardown by yielding until the next line in the destructor can
245cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang             * execute to set mRun = false. Note that the FIFO sends an
246cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang             * empty NONE message when it reaches its destructor.
247cf067b8c4d1e53bc4768fbad239851c579717f2cMiao Wang             */
248221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            usleep(1000);
249221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            break;
250221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        case RS_MESSAGE_TO_CLIENT_USER:
25144bef6fba6244292b751387f3d6c31cca96c28adChris Wailes            if(rs->mMessageFunc != nullptr) {
252221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams                rs->mMessageFunc(usrID, rbuf, receiveLen);
253221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            } else {
254221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams                ALOGE("Received a message from the script with no message handler installed.");
255221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            }
256221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams            break;
257221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
258221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        default:
25984bf2b877024aaa154b66e0f2338d54bdabd855aTim Murray            ALOGE("RS unknown message type %i", r);
260221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        }
261221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    }
262221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
263221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    if (rbuf) {
264221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams        free(rbuf);
265221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    }
26687c9d77a3be0dff4a4413bbb6f5b91014896e048Tim Murray    ALOGV("RS Message thread exiting.");
26744bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    return nullptr;
268221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams}
269221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
27084bf2b877024aaa154b66e0f2338d54bdabd855aTim Murrayvoid RS::setErrorHandler(ErrorHandlerFunc_t func) {
271221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    mErrorFunc = func;
272221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams}
273221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams
27484bf2b877024aaa154b66e0f2338d54bdabd855aTim Murrayvoid RS::setMessageHandler(MessageHandlerFunc_t func) {
275221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams    mMessageFunc  = func;
276221a4b17cda03916a0599628fcbb5f48605a0e5aJason Sams}
277baca6c3c3d79a324c7976ba873afdded0b6bcfb5Tim Murray
278baca6c3c3d79a324c7976ba873afdded0b6bcfb5Tim Murrayvoid RS::finish() {
279a423096c0d49e5cfe13a400b4323a76f89c6885cTim Murray    RS::dispatch->ContextFinish(mContext);
280baca6c3c3d79a324c7976ba873afdded0b6bcfb5Tim Murray}
281