public void run() { // This function is a temporary solution. The final solution will // used typed allocations where the message id is the type indicator. int[] rbuf = new int[16]; mRS.nContextInitToClient(mRS.mContext); while (mRun) { rbuf[0] = 0; int msg = mRS.nContextPeekMessage(mRS.mContext, mAuxData); int size = mAuxData[1]; int subID = mAuxData[0]; if (msg == RS_MESSAGE_TO_CLIENT_USER) { if ((size >> 2) >= rbuf.length) { rbuf = new int[(size + 3) >> 2]; } if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) != RS_MESSAGE_TO_CLIENT_USER) { throw new RSDriverException("Error processing message from RenderScript."); } if (mRS.mMessageCallback != null) { mRS.mMessageCallback.mData = rbuf; mRS.mMessageCallback.mID = subID; mRS.mMessageCallback.mLength = size; mRS.mMessageCallback.run(); } else { throw new RSInvalidStateException( "Received a message from the script with no message handler installed."); } continue; } if (msg == RS_MESSAGE_TO_CLIENT_ERROR) { String e = mRS.nContextGetErrorMessage(mRS.mContext); // Throw RSRuntimeException under the following conditions: // // 1) It is an unknown fatal error. // 2) It is a debug fatal error, and we are not in a // debug context. // 3) It is a debug fatal error, and we do not have an // error callback. if (subID >= RS_ERROR_FATAL_UNKNOWN || (subID >= RS_ERROR_FATAL_DEBUG && (mRS.mContextType != ContextType.DEBUG || mRS.mErrorCallback == null))) { throw new RSRuntimeException("Fatal error " + subID + ", details: " + e); } if (mRS.mErrorCallback != null) { mRS.mErrorCallback.mErrorMessage = e; mRS.mErrorCallback.mErrorNum = subID; mRS.mErrorCallback.run(); } else { android.util.Log.e(LOG_TAG, "non fatal RS error, " + e); // Do not throw here. In these cases, we do not have // a fatal error. } continue; } if (msg == RS_MESSAGE_TO_CLIENT_NEW_BUFFER) { if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) != RS_MESSAGE_TO_CLIENT_NEW_BUFFER) { throw new RSDriverException("Error processing message from RenderScript."); } long bufferID = ((long) rbuf[1] << 32L) + ((long) rbuf[0] & 0xffffffffL); Allocation.sendBufferNotification(bufferID); continue; } // 2: teardown. // But we want to avoid starving other threads during // teardown by yielding until the next line in the destructor // can execute to set mRun = false try { sleep(1, 0); } catch (InterruptedException e) { } } // Log.d(LOG_TAG, "MessageThread exiting."); }