1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed 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
17package android.support.v8.renderscript;
18
19import java.io.File;
20import java.lang.reflect.Field;
21import java.lang.reflect.Method;
22import java.util.concurrent.locks.ReentrantReadWriteLock;
23
24import android.content.Context;
25import android.content.pm.ApplicationInfo;
26import android.content.pm.PackageManager;
27import android.content.res.AssetManager;
28import android.graphics.Bitmap;
29import android.graphics.BitmapFactory;
30import android.os.Process;
31import android.util.Log;
32import android.view.Surface;
33import java.util.ArrayList;
34
35/**
36 * This class provides access to a RenderScript context, which controls RenderScript
37 * initialization, resource management, and teardown. An instance of the RenderScript
38 * class must be created before any other RS objects can be created.
39 *
40 * <div class="special reference">
41 * <h3>Developer Guides</h3>
42 * <p>For more information about creating an application that uses RenderScript, read the
43 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
44 * </div>
45 **/
46public class RenderScript {
47    static final String LOG_TAG = "RenderScript_jni";
48    static final boolean DEBUG  = false;
49    @SuppressWarnings({"UnusedDeclaration", "deprecation"})
50    static final boolean LOG_ENABLED = false;
51    static final int SUPPORT_LIB_API = 23;
52
53    static private ArrayList<RenderScript> mProcessContextList = new ArrayList<RenderScript>();
54    private boolean mIsProcessContext = false;
55    private int mContextFlags = 0;
56    private int mContextSdkVersion = 0;
57
58
59    private Context mApplicationContext;
60    private String mNativeLibDir;
61
62    static private String mBlackList = "";
63     /**
64     * Sets the blackList of Models to only use support lib runtime.
65     * Should be used before context create.
66     *
67     * @param blackList User provided black list string.
68     *
69     * Format: "(MANUFACTURER1:PRODUCT1:MODEL1), (MANUFACTURER2:PRODUCT2:MODEL2)..."
70     * e.g. : To Blacklist Nexus 7(2013) and Nexus 5.
71     *        mBlackList = "(asus:razor:Nexus 7), (LGE:hammerhead:Nexus 5)";
72     */
73    static public void setBlackList(String blackList) {
74        if (blackList != null) {
75            mBlackList = blackList;
76        }
77    }
78     /**
79     * Force using support lib runtime.
80     * Should be used before context create.
81     *
82     */
83    static public void forceCompat() {
84        sNative = 0;
85    }
86    /*
87     * We use a class initializer to allow the native code to cache some
88     * field offsets.
89     */
90    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
91    static boolean sInitialized;
92    static boolean sUseGCHooks;
93    static Object sRuntime;
94    static Method registerNativeAllocation;
95    static Method registerNativeFree;
96
97    static Object lock = new Object();
98
99    // Non-threadsafe functions.
100    native boolean nLoadSO(boolean useNative, int deviceApi);
101    native boolean nLoadIOSO();
102    native long nDeviceCreate();
103    native void nDeviceDestroy(long dev);
104    native void nDeviceSetConfig(long dev, int param, int value);
105    native int nContextGetUserMessage(long con, int[] data);
106    native String nContextGetErrorMessage(long con);
107    native int  nContextPeekMessage(long con, int[] subID);
108    native void nContextInitToClient(long con);
109    native void nContextDeinitToClient(long con);
110
111    static private int sNative = -1;
112    static private int sSdkVersion = -1;
113    static private boolean useIOlib = false;
114    static private boolean useNative;
115
116    /*
117     * Context creation flag that specifies a normal context.
118     * RenderScript Support lib only support normal context.
119     */
120    public static final int CREATE_FLAG_NONE = 0x0000;
121
122
123    boolean isUseNative() {
124        return useNative;
125    }
126    /*
127     * Detect the bitness of the VM to allow FieldPacker to do the right thing.
128     */
129    static native int rsnSystemGetPointerSize();
130    static int sPointerSize;
131
132    /**
133     * Determines whether or not we should be thunking into the native
134     * RenderScript layer or actually using the compatibility library.
135     */
136    static private boolean setupNative(int sdkVersion, Context ctx) {
137        // if targetSdkVersion is higher than the device api version, always use compat mode.
138        // Workaround for KK
139        if (android.os.Build.VERSION.SDK_INT < sdkVersion &&
140            android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
141            sNative = 0;
142        }
143
144        if (sNative == -1) {
145
146            // get the value of the debug.rs.forcecompat property
147            int forcecompat = 0;
148            try {
149                Class<?> sysprop = Class.forName("android.os.SystemProperties");
150                Class[] signature = {String.class, Integer.TYPE};
151                Method getint = sysprop.getDeclaredMethod("getInt", signature);
152                Object[] args = {"debug.rs.forcecompat", new Integer(0)};
153                forcecompat = ((java.lang.Integer)getint.invoke(null, args)).intValue();
154            } catch (Exception e) {
155
156            }
157
158            if ((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT)
159                     && forcecompat == 0) {
160                sNative = 1;
161            } else {
162                sNative = 0;
163            }
164
165
166            if (sNative == 1) {
167                // Workarounds that may disable thunking go here
168                ApplicationInfo info = null;
169                try {
170                    info = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(),
171                                                                      PackageManager.GET_META_DATA);
172                } catch (PackageManager.NameNotFoundException e) {
173                    // assume no workarounds needed
174                }
175
176                if (info != null) {
177                    long minorVersion = 0;
178                    // load minorID from reflection
179                    try {
180                        Class<?> javaRS = Class.forName("android.renderscript.RenderScript");
181                        if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
182                            Method getMinorID = javaRS.getDeclaredMethod("getMinorID");
183                            minorVersion = ((java.lang.Long)getMinorID.invoke(null)).longValue();
184                        } else {
185                            //For M+
186                            Method getMinorVersion = javaRS.getDeclaredMethod("getMinorVersion");
187                            minorVersion = ((java.lang.Long)getMinorVersion.invoke(null)).longValue();
188                        }
189                    } catch (Exception e) {
190                        // minor version remains 0 on devices with no possible WARs
191                    }
192
193                    if (info.metaData != null) {
194                        // asynchronous teardown: minor version 1+
195                        if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableAsyncTeardown") == true) {
196                            if (minorVersion == 0) {
197                                sNative = 0;
198                            }
199                        }
200
201                        // blur issues on some drivers with 4.4
202                        if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableBlurWorkaround") == true) {
203                            if (android.os.Build.VERSION.SDK_INT <= 19) {
204                                //android.util.Log.e("rs", "war on");
205                                sNative = 0;
206                            }
207                        }
208                    }
209                    // end of workarounds
210                }
211            }
212        }
213
214        if (sNative == 1) {
215            // check against the blacklist
216            if (mBlackList.length() > 0) {
217                String deviceInfo = '(' +
218                                    android.os.Build.MANUFACTURER +
219                                    ':' +
220                                    android.os.Build.PRODUCT +
221                                    ':' +
222                                    android.os.Build.MODEL +
223                                    ')';
224                if (mBlackList.contains(deviceInfo)) {
225                    sNative = 0;
226                    return false;
227                }
228            }
229            return true;
230        }
231        return false;
232    }
233
234    /**
235     * Name of the file that holds the object cache.
236     */
237    private static final String CACHE_PATH = "com.android.renderscript.cache";
238    static String mCachePath;
239
240     /**
241     * Sets the directory to use as a persistent storage for the
242     * renderscript object file cache.
243     *
244     * @hide
245     * @param cacheDir A directory the current process can write to
246     */
247    public static void setupDiskCache(File cacheDir) {
248        File f = new File(cacheDir, CACHE_PATH);
249        mCachePath = f.getAbsolutePath();
250        f.mkdirs();
251    }
252
253    /**
254     * ContextType specifies the specific type of context to be created.
255     *
256     */
257    public enum ContextType {
258        /**
259         * NORMAL context, this is the default and what shipping apps should
260         * use.
261         */
262        NORMAL (0),
263
264        /**
265         * DEBUG context, perform extra runtime checks to validate the
266         * kernels and APIs are being used as intended.  Get and SetElementAt
267         * will be bounds checked in this mode.
268         */
269        DEBUG (1),
270
271        /**
272         * PROFILE context, Intended to be used once the first time an
273         * application is run on a new device.  This mode allows the runtime to
274         * do additional testing and performance tuning.
275         */
276        PROFILE (2);
277
278        int mID;
279        ContextType(int id) {
280            mID = id;
281        }
282    }
283
284    ContextType mContextType;
285    // Methods below are wrapped to protect the non-threadsafe
286    // lockless fifo.
287
288    native long  rsnContextCreate(long dev, int ver, int sdkVer, int contextType, String nativeLibDir);
289    synchronized long nContextCreate(long dev, int ver, int sdkVer, int contextType, String nativeLibDir) {
290        return rsnContextCreate(dev, ver, sdkVer, contextType, nativeLibDir);
291    }
292    native void rsnContextDestroy(long con);
293    synchronized void nContextDestroy() {
294        validate();
295
296        // take teardown lock
297        // teardown lock can only be taken when no objects are being destroyed
298        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
299        wlock.lock();
300
301        long curCon = mContext;
302        // context is considered dead as of this point
303        mContext = 0;
304
305        wlock.unlock();
306        rsnContextDestroy(curCon);
307    }
308    native void rsnContextSetPriority(long con, int p);
309    synchronized void nContextSetPriority(int p) {
310        validate();
311        rsnContextSetPriority(mContext, p);
312    }
313    native void rsnContextDump(long con, int bits);
314    synchronized void nContextDump(int bits) {
315        validate();
316        rsnContextDump(mContext, bits);
317    }
318    native void rsnContextFinish(long con);
319    synchronized void nContextFinish() {
320        validate();
321        rsnContextFinish(mContext);
322    }
323
324    native void rsnContextSendMessage(long con, int id, int[] data);
325    synchronized void nContextSendMessage(int id, int[] data) {
326        validate();
327        rsnContextSendMessage(mContext, id, data);
328    }
329
330    // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
331    native void rsnObjDestroy(long con, long id);
332    void nObjDestroy(long id) {
333        // There is a race condition here.  The calling code may be run
334        // by the gc while teardown is occuring.  This protects againts
335        // deleting dead objects.
336        if (mContext != 0) {
337            rsnObjDestroy(mContext, id);
338        }
339    }
340
341    native long  rsnElementCreate(long con, long type, int kind, boolean norm, int vecSize);
342    synchronized long nElementCreate(long type, int kind, boolean norm, int vecSize) {
343        validate();
344        return rsnElementCreate(mContext, type, kind, norm, vecSize);
345    }
346    native long  rsnElementCreate2(long con, long[] elements, String[] names, int[] arraySizes);
347    synchronized long nElementCreate2(long[] elements, String[] names, int[] arraySizes) {
348        validate();
349        return rsnElementCreate2(mContext, elements, names, arraySizes);
350    }
351    native void rsnElementGetNativeData(long con, long id, int[] elementData);
352    synchronized void nElementGetNativeData(long id, int[] elementData) {
353        validate();
354        rsnElementGetNativeData(mContext, id, elementData);
355    }
356    native void rsnElementGetSubElements(long con, long id,
357                                         long[] IDs, String[] names, int[] arraySizes);
358    synchronized void nElementGetSubElements(long id, long[] IDs, String[] names, int[] arraySizes) {
359        validate();
360        rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
361    }
362
363    native long rsnTypeCreate(long con, long eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
364    synchronized long nTypeCreate(long eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
365        validate();
366        return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
367    }
368
369    native void rsnTypeGetNativeData(long con, long id, long[] typeData);
370    synchronized void nTypeGetNativeData(long id, long[] typeData) {
371        validate();
372        rsnTypeGetNativeData(mContext, id, typeData);
373    }
374
375    native long  rsnAllocationCreateTyped(long con, long type, int mip, int usage, long pointer);
376    synchronized long nAllocationCreateTyped(long type, int mip, int usage, long pointer) {
377        validate();
378        return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
379    }
380    native long  rsnAllocationCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage);
381    synchronized long nAllocationCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
382        validate();
383        return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage);
384    }
385
386    native long  rsnAllocationCreateBitmapBackedAllocation(long con, long type, int mip, Bitmap bmp, int usage);
387    synchronized long nAllocationCreateBitmapBackedAllocation(long type, int mip, Bitmap bmp, int usage) {
388        validate();
389        return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp, usage);
390    }
391
392
393    native long  rsnAllocationCubeCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage);
394    synchronized long nAllocationCubeCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
395        validate();
396        return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage);
397    }
398    native long  rsnAllocationCreateBitmapRef(long con, long type, Bitmap bmp);
399    synchronized long nAllocationCreateBitmapRef(long type, Bitmap bmp) {
400        validate();
401        return rsnAllocationCreateBitmapRef(mContext, type, bmp);
402    }
403    native long  rsnAllocationCreateFromAssetStream(long con, int mips, int assetStream, int usage);
404    synchronized long nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) {
405        validate();
406        return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage);
407    }
408
409    native void  rsnAllocationCopyToBitmap(long con, long alloc, Bitmap bmp);
410    synchronized void nAllocationCopyToBitmap(long alloc, Bitmap bmp) {
411        validate();
412        rsnAllocationCopyToBitmap(mContext, alloc, bmp);
413    }
414
415
416    native void rsnAllocationSyncAll(long con, long alloc, int src);
417    synchronized void nAllocationSyncAll(long alloc, int src) {
418        validate();
419        rsnAllocationSyncAll(mContext, alloc, src);
420    }
421
422    native void rsnAllocationSetSurface(long con, long alloc, Surface sur);
423    synchronized void nAllocationSetSurface(long alloc, Surface sur) {
424        validate();
425        rsnAllocationSetSurface(mContext, alloc, sur);
426    }
427
428    native void rsnAllocationIoSend(long con, long alloc);
429    synchronized void nAllocationIoSend(long alloc) {
430        validate();
431        rsnAllocationIoSend(mContext, alloc);
432    }
433    native void rsnAllocationIoReceive(long con, long alloc);
434    synchronized void nAllocationIoReceive(long alloc) {
435        validate();
436        rsnAllocationIoReceive(mContext, alloc);
437    }
438
439
440    native void rsnAllocationGenerateMipmaps(long con, long alloc);
441    synchronized void nAllocationGenerateMipmaps(long alloc) {
442        validate();
443        rsnAllocationGenerateMipmaps(mContext, alloc);
444    }
445    native void  rsnAllocationCopyFromBitmap(long con, long alloc, Bitmap bmp);
446    synchronized void nAllocationCopyFromBitmap(long alloc, Bitmap bmp) {
447        validate();
448        rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
449    }
450
451
452    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, Object d, int sizeBytes, int dt,
453                                    int mSize, boolean usePadding);
454    synchronized void nAllocationData1D(long id, int off, int mip, int count, Object d, int sizeBytes, Element.DataType dt,
455                                        int mSize, boolean usePadding) {
456        validate();
457        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID, mSize, usePadding);
458    }
459
460    native void rsnAllocationElementData1D(long con,long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
461    synchronized void nAllocationElementData1D(long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
462        validate();
463        rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
464    }
465    /*
466    native void rsnAllocationElementData(long con,long id, int xoff, int yoff, int zoff, int mip, int compIdx, byte[] d, int sizeBytes);
467    synchronized void nAllocationElementData(long id, int xoff, int yoff, int zoff, int mip, int compIdx, byte[] d, int sizeBytes) {
468        validate();
469        rsnAllocationElementData(mContext, id, xoff, yoff, zoff, mip, compIdx, d, sizeBytes);
470    }
471    */
472
473    native void rsnAllocationData2D(long con,
474                                    long dstAlloc, int dstXoff, int dstYoff,
475                                    int dstMip, int dstFace,
476                                    int width, int height,
477                                    long srcAlloc, int srcXoff, int srcYoff,
478                                    int srcMip, int srcFace);
479    synchronized void nAllocationData2D(long dstAlloc, int dstXoff, int dstYoff,
480                                        int dstMip, int dstFace,
481                                        int width, int height,
482                                        long srcAlloc, int srcXoff, int srcYoff,
483                                        int srcMip, int srcFace) {
484        validate();
485        rsnAllocationData2D(mContext,
486                            dstAlloc, dstXoff, dstYoff,
487                            dstMip, dstFace,
488                            width, height,
489                            srcAlloc, srcXoff, srcYoff,
490                            srcMip, srcFace);
491    }
492
493    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face,
494                                    int w, int h, Object d, int sizeBytes, int dt,
495                                    int mSize, boolean usePadding);
496    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face,
497                                        int w, int h, Object d, int sizeBytes, Element.DataType dt,
498                                        int mSize, boolean usePadding) {
499        validate();
500        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID, mSize, usePadding);
501    }
502
503    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face, Bitmap b);
504    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face, Bitmap b) {
505        validate();
506        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
507    }
508
509    native void rsnAllocationData3D(long con,
510                                    long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
511                                    int dstMip,
512                                    int width, int height, int depth,
513                                    long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
514                                    int srcMip);
515    synchronized void nAllocationData3D(long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
516                                        int dstMip,
517                                        int width, int height, int depth,
518                                        long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
519                                        int srcMip) {
520        validate();
521        rsnAllocationData3D(mContext,
522                            dstAlloc, dstXoff, dstYoff, dstZoff,
523                            dstMip, width, height, depth,
524                            srcAlloc, srcXoff, srcYoff, srcZoff, srcMip);
525    }
526
527
528    native void rsnAllocationData3D(long con, long id, int xoff, int yoff, int zoff, int mip,
529                                    int w, int h, int depth, Object d, int sizeBytes, int dt,
530                                    int mSize, boolean usePadding);
531    synchronized void nAllocationData3D(long id, int xoff, int yoff, int zoff, int mip,
532                                        int w, int h, int depth, Object d, int sizeBytes, Element.DataType dt,
533                                        int mSize, boolean usePadding) {
534        validate();
535        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes,
536                            dt.mID, mSize, usePadding);
537    }
538
539    native void rsnAllocationRead(long con, long id, Object d, int dt, int mSize, boolean usePadding);
540    synchronized void nAllocationRead(long id, Object d, Element.DataType dt, int mSize, boolean usePadding) {
541        validate();
542        rsnAllocationRead(mContext, id, d, dt.mID, mSize, usePadding);
543    }
544
545    native void rsnAllocationRead1D(long con, long id, int off, int mip, int count, Object d,
546                                    int sizeBytes, int dt, int mSize, boolean usePadding);
547    synchronized void nAllocationRead1D(long id, int off, int mip, int count, Object d,
548                                        int sizeBytes, Element.DataType dt, int mSize, boolean usePadding) {
549        validate();
550        rsnAllocationRead1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID, mSize, usePadding);
551    }
552
553    /*
554    native void rsnAllocationElementRead(long con,long id, int xoff, int yoff, int zoff,
555                                         int mip, int compIdx, byte[] d, int sizeBytes);
556    synchronized void nAllocationElementRead(long id, int xoff, int yoff, int zoff,
557                                             int mip, int compIdx, byte[] d, int sizeBytes) {
558        validate();
559        rsnAllocationElementRead(mContext, id, xoff, yoff, zoff, mip, compIdx, d, sizeBytes);
560    }
561    */
562
563    native void rsnAllocationRead2D(long con, long id, int xoff, int yoff, int mip, int face,
564                                    int w, int h, Object d, int sizeBytes, int dt,
565                                    int mSize, boolean usePadding);
566    synchronized void nAllocationRead2D(long id, int xoff, int yoff, int mip, int face,
567                                        int w, int h, Object d, int sizeBytes, Element.DataType dt,
568                                        int mSize, boolean usePadding) {
569        validate();
570        rsnAllocationRead2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID, mSize, usePadding);
571    }
572
573    /*
574    native void rsnAllocationRead3D(long con, long id, int xoff, int yoff, int zoff, int mip,
575                                    int w, int h, int depth, Object d, int sizeBytes, int dt,
576                                    int mSize, boolean usePadding);
577    synchronized void nAllocationRead3D(long id, int xoff, int yoff, int zoff, int mip,
578                                        int w, int h, int depth, Object d, int sizeBytes, Element.DataType dt,
579                                        int mSize, boolean usePadding) {
580        validate();
581        rsnAllocationRead3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes, dt.mID, mSize, usePadding);
582    }
583    */
584
585    native long  rsnAllocationGetType(long con, long id);
586    synchronized long nAllocationGetType(long id) {
587        validate();
588        return rsnAllocationGetType(mContext, id);
589    }
590
591    native void rsnAllocationResize1D(long con, long id, int dimX);
592    synchronized void nAllocationResize1D(long id, int dimX) {
593        validate();
594        rsnAllocationResize1D(mContext, id, dimX);
595    }
596    native void rsnAllocationResize2D(long con, long id, int dimX, int dimY);
597    synchronized void nAllocationResize2D(long id, int dimX, int dimY) {
598        validate();
599        rsnAllocationResize2D(mContext, id, dimX, dimY);
600    }
601
602    native void rsnScriptBindAllocation(long con, long script, long alloc, int slot, boolean mUseInc);
603    synchronized void nScriptBindAllocation(long script, long alloc, int slot, boolean mUseInc) {
604        validate();
605        long curCon = mContext;
606        if (mUseInc) {
607            curCon = mIncCon;
608        }
609        rsnScriptBindAllocation(curCon, script, alloc, slot, mUseInc);
610    }
611    native void rsnScriptSetTimeZone(long con, long script, byte[] timeZone, boolean mUseInc);
612    synchronized void nScriptSetTimeZone(long script, byte[] timeZone, boolean mUseInc) {
613        validate();
614        long curCon = mContext;
615        if (mUseInc) {
616            curCon = mIncCon;
617        }
618        rsnScriptSetTimeZone(curCon, script, timeZone, mUseInc);
619    }
620    native void rsnScriptInvoke(long con, long id, int slot, boolean mUseInc);
621    synchronized void nScriptInvoke(long id, int slot, boolean mUseInc) {
622        validate();
623        long curCon = mContext;
624        if (mUseInc) {
625            curCon = mIncCon;
626        }
627        rsnScriptInvoke(curCon, id, slot, mUseInc);
628    }
629    native void rsnScriptForEach(long con, long incCon, long id, int slot, long ain, long aout, byte[] params, boolean mUseInc);
630    native void rsnScriptForEach(long con, long incCon, long id, int slot, long ain, long aout, boolean mUseInc);
631    native void rsnScriptForEachClipped(long con, long incCon, long id, int slot, long ain, long aout, byte[] params,
632                                        int xstart, int xend, int ystart, int yend, int zstart, int zend, boolean mUseInc);
633    native void rsnScriptForEachClipped(long con, long incCon, long id, int slot, long ain, long aout,
634                                        int xstart, int xend, int ystart, int yend, int zstart, int zend, boolean mUseInc);
635    synchronized void nScriptForEach(long id, int slot, long ain, long aout, byte[] params, boolean mUseInc) {
636        validate();
637        if (params == null) {
638            rsnScriptForEach(mContext, mIncCon, id, slot, ain, aout, mUseInc);
639        } else {
640            rsnScriptForEach(mContext, mIncCon, id, slot, ain, aout, params, mUseInc);
641        }
642    }
643
644    synchronized void nScriptForEachClipped(long id, int slot, long ain, long aout, byte[] params,
645                                            int xstart, int xend, int ystart, int yend, int zstart, int zend, boolean mUseInc) {
646        validate();
647        if (params == null) {
648            rsnScriptForEachClipped(mContext, mIncCon, id, slot, ain, aout, xstart, xend, ystart, yend, zstart, zend, mUseInc);
649        } else {
650            rsnScriptForEachClipped(mContext, mIncCon, id, slot, ain, aout, params, xstart, xend, ystart, yend, zstart, zend, mUseInc);
651        }
652    }
653
654    native void rsnScriptInvokeV(long con, long id, int slot, byte[] params, boolean mUseInc);
655    synchronized void nScriptInvokeV(long id, int slot, byte[] params, boolean mUseInc) {
656        validate();
657        long curCon = mContext;
658        if (mUseInc) {
659            curCon = mIncCon;
660        }
661        rsnScriptInvokeV(curCon, id, slot, params, mUseInc);
662    }
663    native void rsnScriptSetVarI(long con, long id, int slot, int val, boolean mUseInc);
664    synchronized void nScriptSetVarI(long id, int slot, int val, boolean mUseInc) {
665        validate();
666        long curCon = mContext;
667        if (mUseInc) {
668            curCon = mIncCon;
669        }
670        rsnScriptSetVarI(curCon, id, slot, val, mUseInc);
671    }
672    native void rsnScriptSetVarJ(long con, long id, int slot, long val, boolean mUseInc);
673    synchronized void nScriptSetVarJ(long id, int slot, long val, boolean mUseInc) {
674        validate();
675        long curCon = mContext;
676        if (mUseInc) {
677            curCon = mIncCon;
678        }
679        rsnScriptSetVarJ(curCon, id, slot, val, mUseInc);
680    }
681    native void rsnScriptSetVarF(long con, long id, int slot, float val, boolean mUseInc);
682    synchronized void nScriptSetVarF(long id, int slot, float val, boolean mUseInc) {
683        validate();
684        long curCon = mContext;
685        if (mUseInc) {
686            curCon = mIncCon;
687        }
688        rsnScriptSetVarF(curCon, id, slot, val, mUseInc);
689    }
690    native void rsnScriptSetVarD(long con, long id, int slot, double val, boolean mUseInc);
691    synchronized void nScriptSetVarD(long id, int slot, double val, boolean mUseInc) {
692        validate();
693        long curCon = mContext;
694        if (mUseInc) {
695            curCon = mIncCon;
696        }
697        rsnScriptSetVarD(curCon, id, slot, val, mUseInc);
698    }
699    native void rsnScriptSetVarV(long con, long id, int slot, byte[] val, boolean mUseInc);
700    synchronized void nScriptSetVarV(long id, int slot, byte[] val, boolean mUseInc) {
701        validate();
702        long curCon = mContext;
703        if (mUseInc) {
704            curCon = mIncCon;
705        }
706        rsnScriptSetVarV(curCon, id, slot, val, mUseInc);
707    }
708    native void rsnScriptSetVarVE(long con, long id, int slot, byte[] val,
709                                  long e, int[] dims, boolean mUseInc);
710    synchronized void nScriptSetVarVE(long id, int slot, byte[] val,
711                                      long e, int[] dims, boolean mUseInc) {
712        validate();
713        long curCon = mContext;
714        if (mUseInc) {
715            curCon = mIncCon;
716        }
717        rsnScriptSetVarVE(curCon, id, slot, val, e, dims, mUseInc);
718    }
719    native void rsnScriptSetVarObj(long con, long id, int slot, long val, boolean mUseInc);
720    synchronized void nScriptSetVarObj(long id, int slot, long val, boolean mUseInc) {
721        validate();
722        long curCon = mContext;
723        if (mUseInc) {
724            curCon = mIncCon;
725        }
726        rsnScriptSetVarObj(curCon, id, slot, val, mUseInc);
727    }
728
729    native long  rsnScriptCCreate(long con, String resName, String cacheDir,
730                                 byte[] script, int length);
731    synchronized long nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
732        validate();
733        return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
734    }
735
736    native long  rsnScriptIntrinsicCreate(long con, int id, long eid, boolean mUseInc);
737    synchronized long nScriptIntrinsicCreate(int id, long eid, boolean mUseInc) {
738        validate();
739        if (mUseInc) {
740            if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
741                Log.e(LOG_TAG, "Incremental Intrinsics are not supported, please change targetSdkVersion to >= 21");
742                throw new RSRuntimeException("Incremental Intrinsics are not supported before Lollipop (API 21)");
743            }
744
745            if (!mIncLoaded) {
746                try {
747                    System.loadLibrary("RSSupport");
748                } catch (UnsatisfiedLinkError e) {
749                    Log.e(LOG_TAG, "Error loading RS Compat library for Incremental Intrinsic Support: " + e);
750                    throw new RSRuntimeException("Error loading RS Compat library for Incremental Intrinsic Support: " + e);
751                }
752                if (!nIncLoadSO(SUPPORT_LIB_API)) {
753                    throw new RSRuntimeException("Error loading libRSSupport library for Incremental Intrinsic Support");
754                }
755                mIncLoaded = true;
756            }
757            if (mIncDev == 0) {
758                mIncDev = nIncDeviceCreate();
759            }
760            if (mIncCon == 0) {
761                //Create a dummy compat context (synchronous).
762                mIncCon = nIncContextCreate(mIncDev, 0, 0, 0);
763            }
764            return rsnScriptIntrinsicCreate(mIncCon, id, eid, mUseInc);
765        } else {
766            return rsnScriptIntrinsicCreate(mContext, id, eid, mUseInc);
767        }
768    }
769
770    native long  rsnScriptKernelIDCreate(long con, long sid, int slot, int sig, boolean mUseInc);
771    synchronized long nScriptKernelIDCreate(long sid, int slot, int sig, boolean mUseInc) {
772        validate();
773        long curCon = mContext;
774        if (mUseInc) {
775            curCon = mIncCon;
776        }
777        return rsnScriptKernelIDCreate(curCon, sid, slot, sig, mUseInc);
778    }
779
780    native long  rsnScriptInvokeIDCreate(long con, long sid, int slot);
781    synchronized long nScriptInvokeIDCreate(long sid, int slot) {
782        validate();
783        return rsnScriptInvokeIDCreate(mContext, sid, slot);
784    }
785
786    native long  rsnScriptFieldIDCreate(long con, long sid, int slot, boolean mUseInc);
787    synchronized long nScriptFieldIDCreate(long sid, int slot, boolean mUseInc) {
788        validate();
789        long curCon = mContext;
790        if (mUseInc) {
791            curCon = mIncCon;
792        }
793        return rsnScriptFieldIDCreate(curCon, sid, slot, mUseInc);
794    }
795
796    native long  rsnScriptGroupCreate(long con, long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types);
797    synchronized long nScriptGroupCreate(long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types) {
798        validate();
799        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
800    }
801
802    native void rsnScriptGroupSetInput(long con, long group, long kernel, long alloc);
803    synchronized void nScriptGroupSetInput(long group, long kernel, long alloc) {
804        validate();
805        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
806    }
807
808    native void rsnScriptGroupSetOutput(long con, long group, long kernel, long alloc);
809    synchronized void nScriptGroupSetOutput(long group, long kernel, long alloc) {
810        validate();
811        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
812    }
813
814    native void rsnScriptGroupExecute(long con, long group);
815    synchronized void nScriptGroupExecute(long group) {
816        validate();
817        rsnScriptGroupExecute(mContext, group);
818    }
819
820    native long  rsnSamplerCreate(long con, int magFilter, int minFilter,
821                                 int wrapS, int wrapT, int wrapR, float aniso);
822    synchronized long nSamplerCreate(int magFilter, int minFilter,
823                                 int wrapS, int wrapT, int wrapR, float aniso) {
824        validate();
825        return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
826    }
827
828// entry points for ScriptGroup2
829    native long rsnClosureCreate(long con, long kernelID, long returnValue,
830        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
831        long[] depFieldIDs);
832    synchronized long nClosureCreate(long kernelID, long returnValue,
833        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
834        long[] depFieldIDs) {
835      validate();
836      long c = rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
837          sizes, depClosures, depFieldIDs);
838      if (c == 0) {
839          throw new RSRuntimeException("Failed creating closure.");
840      }
841      return c;
842    }
843
844    native long rsnInvokeClosureCreate(long con, long invokeID, byte[] params,
845        long[] fieldIDs, long[] values, int[] sizes);
846    synchronized long nInvokeClosureCreate(long invokeID, byte[] params,
847        long[] fieldIDs, long[] values, int[] sizes) {
848      validate();
849      long c = rsnInvokeClosureCreate(mContext, invokeID, params, fieldIDs,
850          values, sizes);
851      if (c == 0) {
852          throw new RSRuntimeException("Failed creating closure.");
853      }
854      return c;
855    }
856
857    native void rsnClosureSetArg(long con, long closureID, int index,
858      long value, int size);
859    synchronized void nClosureSetArg(long closureID, int index, long value,
860        int size) {
861      validate();
862      rsnClosureSetArg(mContext, closureID, index, value, size);
863    }
864
865    native void rsnClosureSetGlobal(long con, long closureID, long fieldID,
866        long value, int size);
867    // Does this have to be synchronized?
868    synchronized void nClosureSetGlobal(long closureID, long fieldID,
869        long value, int size) {
870      validate(); // TODO: is this necessary?
871      rsnClosureSetGlobal(mContext, closureID, fieldID, value, size);
872    }
873
874    native long rsnScriptGroup2Create(long con, String name, String cachePath,
875                                      long[] closures);
876    synchronized long nScriptGroup2Create(String name, String cachePath,
877                                          long[] closures) {
878      validate();
879      return rsnScriptGroup2Create(mContext, name, cachePath, closures);
880    }
881
882    native void rsnScriptGroup2Execute(long con, long groupID);
883    synchronized void nScriptGroup2Execute(long groupID) {
884      validate();
885      rsnScriptGroup2Execute(mContext, groupID);
886    }
887
888    native void rsnScriptIntrinsicBLAS_Single(long con, long incCon, long id, int func, int TransA,
889                                              int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
890                                              float alpha, long A, long B, float beta, long C, int incX, int incY,
891                                              int KL, int KU, boolean mUseInc);
892    synchronized void nScriptIntrinsicBLAS_Single(long id, int func, int TransA,
893                                                  int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
894                                                  float alpha, long A, long B, float beta, long C, int incX, int incY,
895                                                  int KL, int KU, boolean mUseInc) {
896        validate();
897        rsnScriptIntrinsicBLAS_Single(mContext, mIncCon, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alpha, A, B, beta, C, incX, incY, KL, KU, mUseInc);
898    }
899
900    native void rsnScriptIntrinsicBLAS_Double(long con, long incCon, long id, int func, int TransA,
901                                              int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
902                                              double alpha, long A, long B, double beta, long C, int incX, int incY,
903                                              int KL, int KU, boolean mUseInc);
904    synchronized void nScriptIntrinsicBLAS_Double(long id, int func, int TransA,
905                                                  int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
906                                                  double alpha, long A, long B, double beta, long C, int incX, int incY,
907                                                  int KL, int KU, boolean mUseInc) {
908        validate();
909        rsnScriptIntrinsicBLAS_Double(mContext, mIncCon, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alpha, A, B, beta, C, incX, incY, KL, KU, mUseInc);
910    }
911
912    native void rsnScriptIntrinsicBLAS_Complex(long con, long incCon, long id, int func, int TransA,
913                                               int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
914                                               float alphaX, float alphaY, long A, long B, float betaX, float betaY, long C, int incX, int incY,
915                                               int KL, int KU, boolean mUseInc);
916    synchronized void nScriptIntrinsicBLAS_Complex(long id, int func, int TransA,
917                                                   int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
918                                                   float alphaX, float alphaY, long A, long B, float betaX, float betaY, long C, int incX, int incY,
919                                                   int KL, int KU, boolean mUseInc) {
920        validate();
921        rsnScriptIntrinsicBLAS_Complex(mContext, mIncCon, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alphaX, alphaY, A, B, betaX, betaY, C, incX, incY, KL, KU, mUseInc);
922    }
923
924    native void rsnScriptIntrinsicBLAS_Z(long con, long incCon, long id, int func, int TransA,
925                                         int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
926                                         double alphaX, double alphaY, long A, long B, double betaX, double betaY, long C, int incX, int incY,
927                                         int KL, int KU, boolean mUseInc);
928    synchronized void nScriptIntrinsicBLAS_Z(long id, int func, int TransA,
929                                             int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
930                                             double alphaX, double alphaY, long A, long B, double betaX, double betaY, long C, int incX, int incY,
931                                             int KL, int KU, boolean mUseInc) {
932        validate();
933        rsnScriptIntrinsicBLAS_Z(mContext, mIncCon, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alphaX, alphaY, A, B, betaX, betaY, C, incX, incY, KL, KU, mUseInc);
934    }
935
936    native void rsnScriptIntrinsicBLAS_BNNM(long con, long incCon, long id, int M, int N, int K,
937                                             long A, int a_offset, long B, int b_offset, long C, int c_offset,
938                                             int c_mult_int, boolean mUseInc);
939    synchronized void nScriptIntrinsicBLAS_BNNM(long id, int M, int N, int K,
940                                             long A, int a_offset, long B, int b_offset, long C, int c_offset,
941                                             int c_mult_int, boolean mUseInc) {
942        validate();
943        rsnScriptIntrinsicBLAS_BNNM(mContext, mIncCon, id, M, N, K, A, a_offset, B, b_offset, C, c_offset, c_mult_int, mUseInc);
944    }
945
946// Additional Entry points For inc libRSSupport
947
948    native boolean nIncLoadSO(int deviceApi);
949    native long nIncDeviceCreate();
950    native void nIncDeviceDestroy(long dev);
951    // Methods below are wrapped to protect the non-threadsafe
952    // lockless fifo.
953    native long  rsnIncContextCreate(long dev, int ver, int sdkVer, int contextType);
954    synchronized long nIncContextCreate(long dev, int ver, int sdkVer, int contextType) {
955        return rsnIncContextCreate(dev, ver, sdkVer, contextType);
956    }
957    native void rsnIncContextDestroy(long con);
958    synchronized void nIncContextDestroy() {
959        validate();
960
961        // take teardown lock
962        // teardown lock can only be taken when no objects are being destroyed
963        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
964        wlock.lock();
965
966        long curCon = mIncCon;
967        // context is considered dead as of this point
968        mIncCon = 0;
969
970        wlock.unlock();
971        rsnIncContextDestroy(curCon);
972    }
973
974    native void rsnIncContextFinish(long con);
975    synchronized void nIncContextFinish() {
976        validate();
977        rsnIncContextFinish(mIncCon);
978    }
979
980    native void rsnIncObjDestroy(long con, long id);
981    void nIncObjDestroy(long id) {
982        // There is a race condition here.  The calling code may be run
983        // by the gc while teardown is occuring.  This protects againts
984        // deleting dead objects.
985        if (mIncCon != 0) {
986            rsnIncObjDestroy(mIncCon, id);
987        }
988    }
989    native long  rsnIncElementCreate(long con, long type, int kind, boolean norm, int vecSize);
990    synchronized long nIncElementCreate(long type, int kind, boolean norm, int vecSize) {
991        validate();
992        return rsnIncElementCreate(mIncCon, type, kind, norm, vecSize);
993    }
994    native long rsnIncTypeCreate(long con, long eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
995    synchronized long nIncTypeCreate(long eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
996        validate();
997        return rsnIncTypeCreate(mIncCon, eid, x, y, z, mips, faces, yuv);
998    }
999    native long  rsnIncAllocationCreateTyped(long con, long incCon, long alloc, long type);
1000    synchronized long nIncAllocationCreateTyped(long alloc, long type) {
1001        validate();
1002        return rsnIncAllocationCreateTyped(mContext, mIncCon, alloc, type);
1003    }
1004
1005    long     mDev;
1006    long     mContext;
1007    //Dummy device & context for Inc Support Lib
1008    long     mIncDev;
1009    long     mIncCon;
1010    //indicator of whether inc support lib has been loaded or not.
1011    boolean  mIncLoaded;
1012    ReentrantReadWriteLock mRWLock;
1013    @SuppressWarnings({"FieldCanBeLocal"})
1014    MessageThread mMessageThread;
1015
1016    Element mElement_U8;
1017    Element mElement_I8;
1018    Element mElement_U16;
1019    Element mElement_I16;
1020    Element mElement_U32;
1021    Element mElement_I32;
1022    Element mElement_U64;
1023    Element mElement_I64;
1024    Element mElement_F32;
1025    Element mElement_F64;
1026    Element mElement_BOOLEAN;
1027
1028    Element mElement_ELEMENT;
1029    Element mElement_TYPE;
1030    Element mElement_ALLOCATION;
1031    Element mElement_SAMPLER;
1032    Element mElement_SCRIPT;
1033
1034    Element mElement_A_8;
1035    Element mElement_RGB_565;
1036    Element mElement_RGB_888;
1037    Element mElement_RGBA_5551;
1038    Element mElement_RGBA_4444;
1039    Element mElement_RGBA_8888;
1040
1041    Element mElement_FLOAT_2;
1042    Element mElement_FLOAT_3;
1043    Element mElement_FLOAT_4;
1044
1045    Element mElement_DOUBLE_2;
1046    Element mElement_DOUBLE_3;
1047    Element mElement_DOUBLE_4;
1048
1049    Element mElement_UCHAR_2;
1050    Element mElement_UCHAR_3;
1051    Element mElement_UCHAR_4;
1052
1053    Element mElement_CHAR_2;
1054    Element mElement_CHAR_3;
1055    Element mElement_CHAR_4;
1056
1057    Element mElement_USHORT_2;
1058    Element mElement_USHORT_3;
1059    Element mElement_USHORT_4;
1060
1061    Element mElement_SHORT_2;
1062    Element mElement_SHORT_3;
1063    Element mElement_SHORT_4;
1064
1065    Element mElement_UINT_2;
1066    Element mElement_UINT_3;
1067    Element mElement_UINT_4;
1068
1069    Element mElement_INT_2;
1070    Element mElement_INT_3;
1071    Element mElement_INT_4;
1072
1073    Element mElement_ULONG_2;
1074    Element mElement_ULONG_3;
1075    Element mElement_ULONG_4;
1076
1077    Element mElement_LONG_2;
1078    Element mElement_LONG_3;
1079    Element mElement_LONG_4;
1080
1081    Element mElement_MATRIX_4X4;
1082    Element mElement_MATRIX_3X3;
1083    Element mElement_MATRIX_2X2;
1084
1085    Sampler mSampler_CLAMP_NEAREST;
1086    Sampler mSampler_CLAMP_LINEAR;
1087    Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
1088    Sampler mSampler_WRAP_NEAREST;
1089    Sampler mSampler_WRAP_LINEAR;
1090    Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
1091    Sampler mSampler_MIRRORED_REPEAT_NEAREST;
1092    Sampler mSampler_MIRRORED_REPEAT_LINEAR;
1093    Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
1094
1095
1096    ///////////////////////////////////////////////////////////////////////////////////
1097    //
1098
1099    /**
1100     * The base class from which an application should derive in order
1101     * to receive RS messages from scripts. When a script calls {@code
1102     * rsSendToClient}, the data fields will be filled, and the run
1103     * method will be called on a separate thread.  This will occur
1104     * some time after {@code rsSendToClient} completes in the script,
1105     * as {@code rsSendToClient} is asynchronous. Message handlers are
1106     * not guaranteed to have completed when {@link
1107     * android.support.v8.renderscript.RenderScript#finish} returns.
1108     *
1109     */
1110    public static class RSMessageHandler implements Runnable {
1111        protected int[] mData;
1112        protected int mID;
1113        protected int mLength;
1114        public void run() {
1115        }
1116    }
1117    /**
1118     * If an application is expecting messages, it should set this
1119     * field to an instance of {@link RSMessageHandler}.  This
1120     * instance will receive all the user messages sent from {@code
1121     * sendToClient} by scripts from this context.
1122     *
1123     */
1124    RSMessageHandler mMessageCallback = null;
1125
1126    public void setMessageHandler(RSMessageHandler msg) {
1127        mMessageCallback = msg;
1128    }
1129    public RSMessageHandler getMessageHandler() {
1130        return mMessageCallback;
1131    }
1132
1133    /**
1134     * Place a message into the message queue to be sent back to the message
1135     * handler once all previous commands have been executed.
1136     *
1137     * @param id
1138     * @param data
1139     */
1140    public void sendMessage(int id, int[] data) {
1141        nContextSendMessage(id, data);
1142    }
1143
1144    /**
1145     * The runtime error handler base class.  An application should derive from this class
1146     * if it wishes to install an error handler.  When errors occur at runtime,
1147     * the fields in this class will be filled, and the run method will be called.
1148     *
1149     */
1150    public static class RSErrorHandler implements Runnable {
1151        protected String mErrorMessage;
1152        protected int mErrorNum;
1153        public void run() {
1154        }
1155    }
1156
1157    /**
1158     * Application Error handler.  All runtime errors will be dispatched to the
1159     * instance of RSAsyncError set here.  If this field is null a
1160     * {@link RSRuntimeException} will instead be thrown with details about the error.
1161     * This will cause program termaination.
1162     *
1163     */
1164    RSErrorHandler mErrorCallback = null;
1165
1166    public void setErrorHandler(RSErrorHandler msg) {
1167        mErrorCallback = msg;
1168    }
1169    public RSErrorHandler getErrorHandler() {
1170        return mErrorCallback;
1171    }
1172
1173    /**
1174     * RenderScript worker thread priority enumeration.  The default value is
1175     * NORMAL.  Applications wishing to do background processing should set
1176     * their priority to LOW to avoid starving forground processes.
1177     */
1178    public enum Priority {
1179        LOW (Process.THREAD_PRIORITY_BACKGROUND + (5 * Process.THREAD_PRIORITY_LESS_FAVORABLE)),
1180        NORMAL (Process.THREAD_PRIORITY_DISPLAY);
1181
1182        int mID;
1183        Priority(int id) {
1184            mID = id;
1185        }
1186    }
1187
1188    void validate() {
1189        if (mContext == 0) {
1190            throw new RSInvalidStateException("Calling RS with no Context active.");
1191        }
1192    }
1193
1194    /**
1195     * check if IO support lib is available.
1196     */
1197    boolean usingIO() {
1198        return useIOlib;
1199    }
1200    /**
1201     * Change the priority of the worker threads for this context.
1202     *
1203     * @param p New priority to be set.
1204     */
1205    public void setPriority(Priority p) {
1206        validate();
1207        nContextSetPriority(p.mID);
1208    }
1209
1210    static class MessageThread extends Thread {
1211        RenderScript mRS;
1212        boolean mRun = true;
1213        int[] mAuxData = new int[2];
1214
1215        static final int RS_MESSAGE_TO_CLIENT_NONE = 0;
1216        static final int RS_MESSAGE_TO_CLIENT_EXCEPTION = 1;
1217        static final int RS_MESSAGE_TO_CLIENT_RESIZE = 2;
1218        static final int RS_MESSAGE_TO_CLIENT_ERROR = 3;
1219
1220        static final int RS_MESSAGE_TO_CLIENT_USER = 4;
1221        static final int RS_ERROR_FATAL_UNKNOWN = 0x1000;
1222
1223        MessageThread(RenderScript rs) {
1224            super("RSMessageThread");
1225            mRS = rs;
1226
1227        }
1228
1229        public void run() {
1230            // This function is a temporary solution.  The final solution will
1231            // used typed allocations where the message id is the type indicator.
1232            int[] rbuf = new int[16];
1233            mRS.nContextInitToClient(mRS.mContext);
1234            while(mRun) {
1235                rbuf[0] = 0;
1236                int msg = mRS.nContextPeekMessage(mRS.mContext, mAuxData);
1237                int size = mAuxData[1];
1238                int subID = mAuxData[0];
1239
1240                if (msg == RS_MESSAGE_TO_CLIENT_USER) {
1241                    if ((size>>2) >= rbuf.length) {
1242                        rbuf = new int[(size + 3) >> 2];
1243                    }
1244                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
1245                        RS_MESSAGE_TO_CLIENT_USER) {
1246                        throw new RSDriverException("Error processing message from RenderScript.");
1247                    }
1248
1249                    if(mRS.mMessageCallback != null) {
1250                        mRS.mMessageCallback.mData = rbuf;
1251                        mRS.mMessageCallback.mID = subID;
1252                        mRS.mMessageCallback.mLength = size;
1253                        mRS.mMessageCallback.run();
1254                    } else {
1255                        throw new RSInvalidStateException("Received a message from the script with no message handler installed.");
1256                    }
1257                    continue;
1258                }
1259
1260                if (msg == RS_MESSAGE_TO_CLIENT_ERROR) {
1261                    String e = mRS.nContextGetErrorMessage(mRS.mContext);
1262
1263                    if (subID >= RS_ERROR_FATAL_UNKNOWN) {
1264                        throw new RSRuntimeException("Fatal error " + subID + ", details: " + e);
1265                    }
1266
1267                    if(mRS.mErrorCallback != null) {
1268                        mRS.mErrorCallback.mErrorMessage = e;
1269                        mRS.mErrorCallback.mErrorNum = subID;
1270                        mRS.mErrorCallback.run();
1271                    } else {
1272                        android.util.Log.e(LOG_TAG, "non fatal RS error, " + e);
1273                        // Do not throw here. In these cases, we do not have
1274                        // a fatal error.
1275                    }
1276                    continue;
1277                }
1278
1279                // 2: teardown.
1280                // But we want to avoid starving other threads during
1281                // teardown by yielding until the next line in the destructor
1282                // can execute to set mRun = false
1283                try {
1284                    sleep(1, 0);
1285                } catch(InterruptedException e) {
1286                }
1287            }
1288            //Log.d(LOG_TAG, "MessageThread exiting.");
1289        }
1290    }
1291
1292    RenderScript(Context ctx) {
1293        mContextType = ContextType.NORMAL;
1294        if (ctx != null) {
1295            mApplicationContext = ctx.getApplicationContext();
1296            mNativeLibDir = mApplicationContext.getApplicationInfo().nativeLibraryDir;
1297        }
1298        mIncDev = 0;
1299        mIncCon = 0;
1300        mIncLoaded = false;
1301        mRWLock = new ReentrantReadWriteLock();
1302    }
1303
1304    /**
1305     * Gets the application context associated with the RenderScript context.
1306     *
1307     * @return The application context.
1308     */
1309    public final Context getApplicationContext() {
1310        return mApplicationContext;
1311    }
1312
1313    /**
1314     * Create a RenderScript context.
1315     *
1316     * @param ctx The context.
1317     * @return RenderScript
1318     */
1319    private static RenderScript internalCreate(Context ctx, int sdkVersion, ContextType ct, int flags) {
1320        RenderScript rs = new RenderScript(ctx);
1321
1322        if (sSdkVersion == -1) {
1323            sSdkVersion = sdkVersion;
1324        } else if (sSdkVersion != sdkVersion) {
1325            throw new RSRuntimeException("Can't have two contexts with different SDK versions in support lib");
1326        }
1327        useNative = setupNative(sSdkVersion, ctx);
1328        synchronized(lock) {
1329            if (sInitialized == false) {
1330                try {
1331                    Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
1332                    Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
1333                    sRuntime = get_runtime.invoke(null);
1334                    registerNativeAllocation = vm_runtime.getDeclaredMethod("registerNativeAllocation", Integer.TYPE);
1335                    registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Integer.TYPE);
1336                    sUseGCHooks = true;
1337                } catch (Exception e) {
1338                    Log.e(LOG_TAG, "No GC methods");
1339                    sUseGCHooks = false;
1340                }
1341                try {
1342                    System.loadLibrary("rsjni");
1343                    sInitialized = true;
1344                    sPointerSize = rsnSystemGetPointerSize();
1345                } catch (UnsatisfiedLinkError e) {
1346                    Log.e(LOG_TAG, "Error loading RS jni library: " + e);
1347                    throw new RSRuntimeException("Error loading RS jni library: " + e);
1348                }
1349            }
1350        }
1351
1352        if (useNative) {
1353            android.util.Log.v(LOG_TAG, "RS native mode");
1354        } else {
1355            android.util.Log.v(LOG_TAG, "RS compat mode");
1356        }
1357
1358        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1359            useIOlib = true;
1360        }
1361
1362        int dispatchAPI = sdkVersion;
1363        if (sdkVersion < android.os.Build.VERSION.SDK_INT) {
1364            // If the device API is higher than target API level, init dispatch table based on device API.
1365            dispatchAPI = android.os.Build.VERSION.SDK_INT;
1366        }
1367        if (!rs.nLoadSO(useNative, dispatchAPI)) {
1368            if (useNative) {
1369                android.util.Log.v(LOG_TAG, "Unable to load libRS.so, falling back to compat mode");
1370                useNative = false;
1371            }
1372            try {
1373                System.loadLibrary("RSSupport");
1374            } catch (UnsatisfiedLinkError e) {
1375                Log.e(LOG_TAG, "Error loading RS Compat library: " + e);
1376                throw new RSRuntimeException("Error loading RS Compat library: " + e);
1377            }
1378            if (!rs.nLoadSO(false, dispatchAPI)) {
1379                throw new RSRuntimeException("Error loading libRSSupport library");
1380            }
1381        }
1382
1383        if (useIOlib) {
1384            try {
1385                System.loadLibrary("RSSupportIO");
1386            } catch (UnsatisfiedLinkError e) {
1387                useIOlib = false;
1388            }
1389            if (!useIOlib || !rs.nLoadIOSO()) {
1390                android.util.Log.v(LOG_TAG, "Unable to load libRSSupportIO.so, USAGE_IO not supported");
1391                useIOlib = false;
1392            }
1393        }
1394
1395        rs.mDev = rs.nDeviceCreate();
1396        rs.mContext = rs.nContextCreate(rs.mDev, 0, sdkVersion, ct.mID, rs.mNativeLibDir);
1397        rs.mContextType = ct;
1398        rs.mContextFlags = flags;
1399        rs.mContextSdkVersion = sdkVersion;
1400        if (rs.mContext == 0) {
1401            throw new RSDriverException("Failed to create RS context.");
1402        }
1403        rs.mMessageThread = new MessageThread(rs);
1404        rs.mMessageThread.start();
1405        return rs;
1406    }
1407
1408    /**
1409     * Create a RenderScript context.
1410     *
1411     * See documentation for @create for details
1412     *
1413     * @param ctx The context.
1414     * @return RenderScript
1415     */
1416    public static RenderScript create(Context ctx) {
1417        return create(ctx, ContextType.NORMAL);
1418    }
1419
1420    /**
1421     * calls create(ctx, ct, CREATE_FLAG_NONE)
1422     *
1423     * See documentation for @create for details
1424     *
1425     * @param ctx The context.
1426     * @param ct The type of context to be created.
1427     * @return RenderScript
1428     */
1429    public static RenderScript create(Context ctx, ContextType ct) {
1430        return create(ctx, ct, CREATE_FLAG_NONE);
1431    }
1432
1433    /**
1434     * Gets or creates a RenderScript context of the specified type.
1435     *
1436     * The returned context will be cached for future reuse within
1437     * the process. When an application is finished using
1438     * RenderScript it should call releaseAllContexts()
1439     *
1440     * A process context is a context designed for easy creation and
1441     * lifecycle management.  Multiple calls to this function will
1442     * return the same object provided they are called with the same
1443     * options.  This allows it to be used any time a RenderScript
1444     * context is needed.
1445     *
1446     *
1447     * @param ctx The context.
1448     * @param ct The type of context to be created.
1449     * @param flags The OR of the CREATE_FLAG_* options desired
1450     * @return RenderScript
1451     */
1452    public static RenderScript create(Context ctx, ContextType ct, int flags) {
1453        int v = ctx.getApplicationInfo().targetSdkVersion;
1454        return create(ctx, v, ct, flags);
1455    }
1456
1457    /**
1458     * calls create(ctx, sdkVersion, ContextType.NORMAL, CREATE_FLAG_NONE)
1459     *
1460     * Used by the RenderScriptThunker to maintain backward compatibility.
1461     *
1462     * @hide
1463     * @param ctx The context.
1464     * @param sdkVersion The target SDK Version.
1465     * @return RenderScript
1466     */
1467    public static RenderScript create(Context ctx, int sdkVersion) {
1468        return create(ctx, sdkVersion, ContextType.NORMAL, CREATE_FLAG_NONE);
1469    }
1470
1471
1472    /**
1473     * calls create(ctx, sdkVersion, ct, CREATE_FLAG_NONE)
1474     * Create a RenderScript context.
1475     *
1476     * @hide
1477     * @param ctx The context.
1478     * @return RenderScript
1479     */
1480    public static RenderScript create(Context ctx, int sdkVersion, ContextType ct) {
1481        return create(ctx, sdkVersion, ct, CREATE_FLAG_NONE);
1482    }
1483
1484     /**
1485     * Gets or creates a RenderScript context of the specified type.
1486     *
1487     * @param ctx The context.
1488     * @param ct The type of context to be created.
1489     * @param sdkVersion The target SDK Version.
1490     * @param flags The OR of the CREATE_FLAG_* options desired
1491     * @return RenderScript
1492     */
1493    public static RenderScript create(Context ctx, int sdkVersion, ContextType ct, int flags) {
1494        synchronized (mProcessContextList) {
1495            for (RenderScript prs : mProcessContextList) {
1496                if ((prs.mContextType == ct) &&
1497                    (prs.mContextFlags == flags) &&
1498                    (prs.mContextSdkVersion == sdkVersion)) {
1499
1500                    return prs;
1501                }
1502            }
1503
1504            RenderScript prs = internalCreate(ctx, sdkVersion, ct, flags);
1505            prs.mIsProcessContext = true;
1506            mProcessContextList.add(prs);
1507            return prs;
1508        }
1509    }
1510
1511    /**
1512     *
1513     * Releases all the process contexts.  This is the same as
1514     * calling .destroy() on each unique context retreived with
1515     * create(...). If no contexts have been created this
1516     * function does nothing.
1517     *
1518     * Typically you call this when your application is losing focus
1519     * and will not be using a context for some time.
1520     *
1521     * This has no effect on a context created with
1522     * createMultiContext()
1523     */
1524    public static void releaseAllContexts() {
1525        ArrayList<RenderScript> oldList;
1526        synchronized (mProcessContextList) {
1527            oldList = mProcessContextList;
1528            mProcessContextList = new ArrayList<RenderScript>();
1529        }
1530
1531        for (RenderScript prs : oldList) {
1532            prs.mIsProcessContext = false;
1533            prs.destroy();
1534        }
1535        oldList.clear();
1536    }
1537
1538
1539
1540    /**
1541     * Create a RenderScript context.
1542     *
1543     * This is an advanced function intended for applications which
1544     * need to create more than one RenderScript context to be used
1545     * at the same time.
1546     *
1547     * If you need a single context please use create()
1548     *
1549     * @param ctx The context.
1550     * @return RenderScript
1551     */
1552    public static RenderScript createMultiContext(Context ctx, ContextType ct, int flags, int API_number) {
1553        return internalCreate(ctx, API_number, ct, flags);
1554    }
1555
1556    /**
1557     * Print the currently available debugging information about the state of
1558     * the RS context to the log.
1559     *
1560     */
1561    public void contextDump() {
1562        validate();
1563        nContextDump(0);
1564    }
1565
1566    /**
1567     * Wait for any pending asynchronous opeations (such as copies to a RS
1568     * allocation or RS script executions) to complete.
1569     *
1570     */
1571    public void finish() {
1572        nContextFinish();
1573    }
1574
1575    /**
1576     * Destroys this RenderScript context.  Once this function is called,
1577     * using this context or any objects belonging to this context is
1578     * illegal.
1579     *
1580     * This function is a NOP if the context was created
1581     * with create().  Please use releaseAllContexts() to clean up
1582     * contexts created with the create function.
1583     */
1584    public void destroy() {
1585        if (mIsProcessContext) {
1586            // users cannot destroy a process context
1587            return;
1588        }
1589        validate();
1590        nContextFinish();
1591        if (mIncCon != 0) {
1592            nIncContextFinish();
1593            nIncContextDestroy();
1594            mIncCon = 0;
1595        }
1596        nContextDeinitToClient(mContext);
1597        mMessageThread.mRun = false;
1598        try {
1599            mMessageThread.join();
1600        } catch(InterruptedException e) {
1601        }
1602
1603        nContextDestroy();
1604        nDeviceDestroy(mDev);
1605        if (mIncDev != 0) {
1606            nIncDeviceDestroy(mIncDev);
1607            mIncDev = 0;
1608        }
1609        mDev = 0;
1610    }
1611
1612    boolean isAlive() {
1613        return mContext != 0;
1614    }
1615
1616    long safeID(BaseObj o) {
1617        if(o != null) {
1618            return o.getID(this);
1619        }
1620        return 0;
1621    }
1622}
1623