[go: nahoru, domu]

RenderScript.java revision be7b1defb6b11920703b241ba5815fb09487bb02
1/*
2 * Copyright (C) 2008-2012 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.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.graphics.SurfaceTexture;
31import android.os.Process;
32import android.util.Log;
33import android.view.Surface;
34import android.os.SystemProperties;
35import android.os.Trace;
36
37/**
38 * This class provides access to a RenderScript context, which controls RenderScript
39 * initialization, resource management, and teardown. An instance of the RenderScript
40 * class must be created before any other RS objects can be created.
41 *
42 * <div class="special reference">
43 * <h3>Developer Guides</h3>
44 * <p>For more information about creating an application that uses RenderScript, read the
45 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
46 * </div>
47 **/
48public class RenderScript {
49    static final long TRACE_TAG = Trace.TRACE_TAG_RS;
50
51    static final String LOG_TAG = "RenderScript_jni";
52    static final boolean DEBUG  = false;
53    @SuppressWarnings({"UnusedDeclaration", "deprecation"})
54    static final boolean LOG_ENABLED = false;
55
56    private Context mApplicationContext;
57
58    /*
59     * We use a class initializer to allow the native code to cache some
60     * field offsets.
61     */
62    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // TODO: now used locally; remove?
63    static boolean sInitialized;
64    native static void _nInit();
65
66    static Object sRuntime;
67    static Method registerNativeAllocation;
68    static Method registerNativeFree;
69
70    /*
71     * Detect the bitness of the VM to allow FieldPacker to do the right thing.
72     */
73    static native int rsnSystemGetPointerSize();
74    static int sPointerSize;
75
76    static {
77        sInitialized = false;
78        if (!SystemProperties.getBoolean("config.disable_renderscript", false)) {
79            try {
80                Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
81                Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
82                sRuntime = get_runtime.invoke(null);
83                registerNativeAllocation = vm_runtime.getDeclaredMethod("registerNativeAllocation", Integer.TYPE);
84                registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Integer.TYPE);
85            } catch (Exception e) {
86                Log.e(LOG_TAG, "Error loading GC methods: " + e);
87                throw new RSRuntimeException("Error loading GC methods: " + e);
88            }
89            try {
90                System.loadLibrary("rs_jni");
91                _nInit();
92                sInitialized = true;
93                sPointerSize = rsnSystemGetPointerSize();
94            } catch (UnsatisfiedLinkError e) {
95                Log.e(LOG_TAG, "Error loading RS jni library: " + e);
96                throw new RSRuntimeException("Error loading RS jni library: " + e);
97            }
98        }
99    }
100
101    // Non-threadsafe functions.
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 File mCacheDir;
112
113    // this should be a monotonically increasing ID
114    // used in conjunction with the API version of a device
115    static final long sMinorID = 1;
116
117    /**
118     * Returns an identifier that can be used to identify a particular
119     * minor version of RS.
120     *
121     * @hide
122     */
123    public static long getMinorID() {
124        return sMinorID;
125    }
126
127     /**
128     * Sets the directory to use as a persistent storage for the
129     * renderscript object file cache.
130     *
131     * @hide
132     * @param cacheDir A directory the current process can write to
133     */
134    public static void setupDiskCache(File cacheDir) {
135        if (!sInitialized) {
136            Log.e(LOG_TAG, "RenderScript.setupDiskCache() called when disabled");
137            return;
138        }
139
140        // Defer creation of cache path to nScriptCCreate().
141        mCacheDir = cacheDir;
142    }
143
144    /**
145     * ContextType specifies the specific type of context to be created.
146     *
147     */
148    public enum ContextType {
149        /**
150         * NORMAL context, this is the default and what shipping apps should
151         * use.
152         */
153        NORMAL (0),
154
155        /**
156         * DEBUG context, perform extra runtime checks to validate the
157         * kernels and APIs are being used as intended.  Get and SetElementAt
158         * will be bounds checked in this mode.
159         */
160        DEBUG (1),
161
162        /**
163         * PROFILE context, Intended to be used once the first time an
164         * application is run on a new device.  This mode allows the runtime to
165         * do additional testing and performance tuning.
166         */
167        PROFILE (2);
168
169        int mID;
170        ContextType(int id) {
171            mID = id;
172        }
173    }
174
175    ContextType mContextType;
176    ReentrantReadWriteLock mRWLock;
177
178    // Methods below are wrapped to protect the non-threadsafe
179    // lockless fifo.
180    native long  rsnContextCreateGL(long dev, int ver, int sdkVer,
181                 int colorMin, int colorPref,
182                 int alphaMin, int alphaPref,
183                 int depthMin, int depthPref,
184                 int stencilMin, int stencilPref,
185                 int samplesMin, int samplesPref, float samplesQ, int dpi);
186    synchronized long nContextCreateGL(long dev, int ver, int sdkVer,
187                 int colorMin, int colorPref,
188                 int alphaMin, int alphaPref,
189                 int depthMin, int depthPref,
190                 int stencilMin, int stencilPref,
191                 int samplesMin, int samplesPref, float samplesQ, int dpi) {
192        return rsnContextCreateGL(dev, ver, sdkVer, colorMin, colorPref,
193                                  alphaMin, alphaPref, depthMin, depthPref,
194                                  stencilMin, stencilPref,
195                                  samplesMin, samplesPref, samplesQ, dpi);
196    }
197    native long  rsnContextCreate(long dev, int ver, int sdkVer, int contextType);
198    synchronized long nContextCreate(long dev, int ver, int sdkVer, int contextType) {
199        return rsnContextCreate(dev, ver, sdkVer, contextType);
200    }
201    native void rsnContextDestroy(long con);
202    synchronized void nContextDestroy() {
203        validate();
204
205        // take teardown lock
206        // teardown lock can only be taken when no objects are being destroyed
207        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
208        wlock.lock();
209
210        long curCon = mContext;
211        // context is considered dead as of this point
212        mContext = 0;
213
214        wlock.unlock();
215        rsnContextDestroy(curCon);
216    }
217    native void rsnContextSetSurface(long con, int w, int h, Surface sur);
218    synchronized void nContextSetSurface(int w, int h, Surface sur) {
219        validate();
220        rsnContextSetSurface(mContext, w, h, sur);
221    }
222    native void rsnContextSetSurfaceTexture(long con, int w, int h, SurfaceTexture sur);
223    synchronized void nContextSetSurfaceTexture(int w, int h, SurfaceTexture sur) {
224        validate();
225        rsnContextSetSurfaceTexture(mContext, w, h, sur);
226    }
227    native void rsnContextSetPriority(long con, int p);
228    synchronized void nContextSetPriority(int p) {
229        validate();
230        rsnContextSetPriority(mContext, p);
231    }
232    native void rsnContextDump(long con, int bits);
233    synchronized void nContextDump(int bits) {
234        validate();
235        rsnContextDump(mContext, bits);
236    }
237    native void rsnContextFinish(long con);
238    synchronized void nContextFinish() {
239        validate();
240        rsnContextFinish(mContext);
241    }
242
243    native void rsnContextSendMessage(long con, int id, int[] data);
244    synchronized void nContextSendMessage(int id, int[] data) {
245        validate();
246        rsnContextSendMessage(mContext, id, data);
247    }
248
249    native void rsnContextBindRootScript(long con, long script);
250    synchronized void nContextBindRootScript(long script) {
251        validate();
252        rsnContextBindRootScript(mContext, script);
253    }
254    native void rsnContextBindSampler(long con, int sampler, int slot);
255    synchronized void nContextBindSampler(int sampler, int slot) {
256        validate();
257        rsnContextBindSampler(mContext, sampler, slot);
258    }
259    native void rsnContextBindProgramStore(long con, long pfs);
260    synchronized void nContextBindProgramStore(long pfs) {
261        validate();
262        rsnContextBindProgramStore(mContext, pfs);
263    }
264    native void rsnContextBindProgramFragment(long con, long pf);
265    synchronized void nContextBindProgramFragment(long pf) {
266        validate();
267        rsnContextBindProgramFragment(mContext, pf);
268    }
269    native void rsnContextBindProgramVertex(long con, long pv);
270    synchronized void nContextBindProgramVertex(long pv) {
271        validate();
272        rsnContextBindProgramVertex(mContext, pv);
273    }
274    native void rsnContextBindProgramRaster(long con, long pr);
275    synchronized void nContextBindProgramRaster(long pr) {
276        validate();
277        rsnContextBindProgramRaster(mContext, pr);
278    }
279    native void rsnContextPause(long con);
280    synchronized void nContextPause() {
281        validate();
282        rsnContextPause(mContext);
283    }
284    native void rsnContextResume(long con);
285    synchronized void nContextResume() {
286        validate();
287        rsnContextResume(mContext);
288    }
289
290    native void rsnAssignName(long con, long obj, byte[] name);
291    synchronized void nAssignName(long obj, byte[] name) {
292        validate();
293        rsnAssignName(mContext, obj, name);
294    }
295    native String rsnGetName(long con, long obj);
296    synchronized String nGetName(long obj) {
297        validate();
298        return rsnGetName(mContext, obj);
299    }
300
301    // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
302    native void rsnObjDestroy(long con, long id);
303    void nObjDestroy(long id) {
304        // There is a race condition here.  The calling code may be run
305        // by the gc while teardown is occuring.  This protects againts
306        // deleting dead objects.
307        if (mContext != 0) {
308            rsnObjDestroy(mContext, id);
309        }
310    }
311
312    native long rsnElementCreate(long con, long type, int kind, boolean norm, int vecSize);
313    synchronized long nElementCreate(long type, int kind, boolean norm, int vecSize) {
314        validate();
315        return rsnElementCreate(mContext, type, kind, norm, vecSize);
316    }
317    native long rsnElementCreate2(long con, long[] elements, String[] names, int[] arraySizes);
318    synchronized long nElementCreate2(long[] elements, String[] names, int[] arraySizes) {
319        validate();
320        return rsnElementCreate2(mContext, elements, names, arraySizes);
321    }
322    native void rsnElementGetNativeData(long con, long id, int[] elementData);
323    synchronized void nElementGetNativeData(long id, int[] elementData) {
324        validate();
325        rsnElementGetNativeData(mContext, id, elementData);
326    }
327    native void rsnElementGetSubElements(long con, long id,
328                                         long[] IDs, String[] names, int[] arraySizes);
329    synchronized void nElementGetSubElements(long id, long[] IDs, String[] names, int[] arraySizes) {
330        validate();
331        rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
332    }
333
334    native long rsnTypeCreate(long con, long eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
335    synchronized long nTypeCreate(long eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
336        validate();
337        return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
338    }
339    native void rsnTypeGetNativeData(long con, long id, long[] typeData);
340    synchronized void nTypeGetNativeData(long id, long[] typeData) {
341        validate();
342        rsnTypeGetNativeData(mContext, id, typeData);
343    }
344
345    native long rsnAllocationCreateTyped(long con, long type, int mip, int usage, long pointer);
346    synchronized long nAllocationCreateTyped(long type, int mip, int usage, long pointer) {
347        validate();
348        return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
349    }
350    native long rsnAllocationCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage);
351    synchronized long nAllocationCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
352        validate();
353        return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage);
354    }
355
356    native long rsnAllocationCreateBitmapBackedAllocation(long con, long type, int mip, Bitmap bmp, int usage);
357    synchronized long nAllocationCreateBitmapBackedAllocation(long type, int mip, Bitmap bmp, int usage) {
358        validate();
359        return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp, usage);
360    }
361
362    native long rsnAllocationCubeCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage);
363    synchronized long nAllocationCubeCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
364        validate();
365        return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage);
366    }
367    native long  rsnAllocationCreateBitmapRef(long con, long type, Bitmap bmp);
368    synchronized long nAllocationCreateBitmapRef(long type, Bitmap bmp) {
369        validate();
370        return rsnAllocationCreateBitmapRef(mContext, type, bmp);
371    }
372    native long  rsnAllocationCreateFromAssetStream(long con, int mips, int assetStream, int usage);
373    synchronized long nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) {
374        validate();
375        return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage);
376    }
377
378    native void  rsnAllocationCopyToBitmap(long con, long alloc, Bitmap bmp);
379    synchronized void nAllocationCopyToBitmap(long alloc, Bitmap bmp) {
380        validate();
381        rsnAllocationCopyToBitmap(mContext, alloc, bmp);
382    }
383
384
385    native void rsnAllocationSyncAll(long con, long alloc, int src);
386    synchronized void nAllocationSyncAll(long alloc, int src) {
387        validate();
388        rsnAllocationSyncAll(mContext, alloc, src);
389    }
390    native Surface rsnAllocationGetSurface(long con, long alloc);
391    synchronized Surface nAllocationGetSurface(long alloc) {
392        validate();
393        return rsnAllocationGetSurface(mContext, alloc);
394    }
395    native void rsnAllocationSetSurface(long con, long alloc, Surface sur);
396    synchronized void nAllocationSetSurface(long alloc, Surface sur) {
397        validate();
398        rsnAllocationSetSurface(mContext, alloc, sur);
399    }
400    native void rsnAllocationIoSend(long con, long alloc);
401    synchronized void nAllocationIoSend(long alloc) {
402        validate();
403        rsnAllocationIoSend(mContext, alloc);
404    }
405    native void rsnAllocationIoReceive(long con, long alloc);
406    synchronized void nAllocationIoReceive(long alloc) {
407        validate();
408        rsnAllocationIoReceive(mContext, alloc);
409    }
410
411
412    native void rsnAllocationGenerateMipmaps(long con, long alloc);
413    synchronized void nAllocationGenerateMipmaps(long alloc) {
414        validate();
415        rsnAllocationGenerateMipmaps(mContext, alloc);
416    }
417    native void  rsnAllocationCopyFromBitmap(long con, long alloc, Bitmap bmp);
418    synchronized void nAllocationCopyFromBitmap(long alloc, Bitmap bmp) {
419        validate();
420        rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
421    }
422
423
424    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, Object d, int sizeBytes, int dt);
425    synchronized void nAllocationData1D(long id, int off, int mip, int count, Object d, int sizeBytes, Element.DataType dt) {
426        validate();
427        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID);
428    }
429
430    native void rsnAllocationElementData1D(long con,long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
431    synchronized void nAllocationElementData1D(long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
432        validate();
433        rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
434    }
435
436    native void rsnAllocationData2D(long con,
437                                    long dstAlloc, int dstXoff, int dstYoff,
438                                    int dstMip, int dstFace,
439                                    int width, int height,
440                                    long srcAlloc, int srcXoff, int srcYoff,
441                                    int srcMip, int srcFace);
442    synchronized void nAllocationData2D(long dstAlloc, int dstXoff, int dstYoff,
443                                        int dstMip, int dstFace,
444                                        int width, int height,
445                                        long srcAlloc, int srcXoff, int srcYoff,
446                                        int srcMip, int srcFace) {
447        validate();
448        rsnAllocationData2D(mContext,
449                            dstAlloc, dstXoff, dstYoff,
450                            dstMip, dstFace,
451                            width, height,
452                            srcAlloc, srcXoff, srcYoff,
453                            srcMip, srcFace);
454    }
455
456    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face,
457                                    int w, int h, Object d, int sizeBytes, int dt);
458    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face,
459                                        int w, int h, Object d, int sizeBytes, Element.DataType dt) {
460        validate();
461        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID);
462    }
463
464    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face, Bitmap b);
465    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face, Bitmap b) {
466        validate();
467        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
468    }
469
470    native void rsnAllocationData3D(long con,
471                                    long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
472                                    int dstMip,
473                                    int width, int height, int depth,
474                                    long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
475                                    int srcMip);
476    synchronized void nAllocationData3D(long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
477                                        int dstMip,
478                                        int width, int height, int depth,
479                                        long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
480                                        int srcMip) {
481        validate();
482        rsnAllocationData3D(mContext,
483                            dstAlloc, dstXoff, dstYoff, dstZoff,
484                            dstMip, width, height, depth,
485                            srcAlloc, srcXoff, srcYoff, srcZoff, srcMip);
486    }
487
488    native void rsnAllocationData3D(long con, long id, int xoff, int yoff, int zoff, int mip,
489                                    int w, int h, int depth, Object d, int sizeBytes, int dt);
490    synchronized void nAllocationData3D(long id, int xoff, int yoff, int zoff, int mip,
491                                        int w, int h, int depth, Object d, int sizeBytes, Element.DataType dt) {
492        validate();
493        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes, dt.mID);
494    }
495
496    native void rsnAllocationRead(long con, long id, Object d, int dt);
497    synchronized void nAllocationRead(long id, Object d, Element.DataType dt) {
498        validate();
499        rsnAllocationRead(mContext, id, d, dt.mID);
500    }
501
502    native void rsnAllocationRead1D(long con, long id, int off, int mip, int count, Object d,
503                                    int sizeBytes, int dt);
504    synchronized void nAllocationRead1D(long id, int off, int mip, int count, Object d,
505                                        int sizeBytes, Element.DataType dt) {
506        validate();
507        rsnAllocationRead1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID);
508    }
509
510    native void rsnAllocationRead2D(long con, long id, int xoff, int yoff, int mip, int face,
511                                    int w, int h, Object d, int sizeBytes, int dt);
512    synchronized void nAllocationRead2D(long id, int xoff, int yoff, int mip, int face,
513                                        int w, int h, Object d, int sizeBytes, Element.DataType dt) {
514        validate();
515        rsnAllocationRead2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID);
516    }
517
518    native long  rsnAllocationGetType(long con, long id);
519    synchronized long nAllocationGetType(long id) {
520        validate();
521        return rsnAllocationGetType(mContext, id);
522    }
523
524    native void rsnAllocationResize1D(long con, long id, int dimX);
525    synchronized void nAllocationResize1D(long id, int dimX) {
526        validate();
527        rsnAllocationResize1D(mContext, id, dimX);
528    }
529
530    native long rsnFileA3DCreateFromAssetStream(long con, long assetStream);
531    synchronized long nFileA3DCreateFromAssetStream(long assetStream) {
532        validate();
533        return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
534    }
535    native long rsnFileA3DCreateFromFile(long con, String path);
536    synchronized long nFileA3DCreateFromFile(String path) {
537        validate();
538        return rsnFileA3DCreateFromFile(mContext, path);
539    }
540    native long rsnFileA3DCreateFromAsset(long con, AssetManager mgr, String path);
541    synchronized long nFileA3DCreateFromAsset(AssetManager mgr, String path) {
542        validate();
543        return rsnFileA3DCreateFromAsset(mContext, mgr, path);
544    }
545    native int  rsnFileA3DGetNumIndexEntries(long con, long fileA3D);
546    synchronized int nFileA3DGetNumIndexEntries(long fileA3D) {
547        validate();
548        return rsnFileA3DGetNumIndexEntries(mContext, fileA3D);
549    }
550    native void rsnFileA3DGetIndexEntries(long con, long fileA3D, int numEntries, int[] IDs, String[] names);
551    synchronized void nFileA3DGetIndexEntries(long fileA3D, int numEntries, int[] IDs, String[] names) {
552        validate();
553        rsnFileA3DGetIndexEntries(mContext, fileA3D, numEntries, IDs, names);
554    }
555    native long rsnFileA3DGetEntryByIndex(long con, long fileA3D, int index);
556    synchronized long nFileA3DGetEntryByIndex(long fileA3D, int index) {
557        validate();
558        return rsnFileA3DGetEntryByIndex(mContext, fileA3D, index);
559    }
560
561    native long rsnFontCreateFromFile(long con, String fileName, float size, int dpi);
562    synchronized long nFontCreateFromFile(String fileName, float size, int dpi) {
563        validate();
564        return rsnFontCreateFromFile(mContext, fileName, size, dpi);
565    }
566    native long rsnFontCreateFromAssetStream(long con, String name, float size, int dpi, long assetStream);
567    synchronized long nFontCreateFromAssetStream(String name, float size, int dpi, long assetStream) {
568        validate();
569        return rsnFontCreateFromAssetStream(mContext, name, size, dpi, assetStream);
570    }
571    native long rsnFontCreateFromAsset(long con, AssetManager mgr, String path, float size, int dpi);
572    synchronized long nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
573        validate();
574        return rsnFontCreateFromAsset(mContext, mgr, path, size, dpi);
575    }
576
577
578    native void rsnScriptBindAllocation(long con, long script, long alloc, int slot);
579    synchronized void nScriptBindAllocation(long script, long alloc, int slot) {
580        validate();
581        rsnScriptBindAllocation(mContext, script, alloc, slot);
582    }
583    native void rsnScriptSetTimeZone(long con, long script, byte[] timeZone);
584    synchronized void nScriptSetTimeZone(long script, byte[] timeZone) {
585        validate();
586        rsnScriptSetTimeZone(mContext, script, timeZone);
587    }
588    native void rsnScriptInvoke(long con, long id, int slot);
589    synchronized void nScriptInvoke(long id, int slot) {
590        validate();
591        rsnScriptInvoke(mContext, id, slot);
592    }
593
594    native void rsnScriptForEach(long con, long id, int slot, long[] ains,
595                                 long aout, byte[] params, int[] limits);
596
597    synchronized void nScriptForEach(long id, int slot, long[] ains, long aout,
598                                     byte[] params, int[] limits) {
599        validate();
600        rsnScriptForEach(mContext, id, slot, ains, aout, params, limits);
601    }
602
603    native void rsnScriptInvokeV(long con, long id, int slot, byte[] params);
604    synchronized void nScriptInvokeV(long id, int slot, byte[] params) {
605        validate();
606        rsnScriptInvokeV(mContext, id, slot, params);
607    }
608
609    native void rsnScriptSetVarI(long con, long id, int slot, int val);
610    synchronized void nScriptSetVarI(long id, int slot, int val) {
611        validate();
612        rsnScriptSetVarI(mContext, id, slot, val);
613    }
614    native int rsnScriptGetVarI(long con, long id, int slot);
615    synchronized int nScriptGetVarI(long id, int slot) {
616        validate();
617        return rsnScriptGetVarI(mContext, id, slot);
618    }
619
620    native void rsnScriptSetVarJ(long con, long id, int slot, long val);
621    synchronized void nScriptSetVarJ(long id, int slot, long val) {
622        validate();
623        rsnScriptSetVarJ(mContext, id, slot, val);
624    }
625    native long rsnScriptGetVarJ(long con, long id, int slot);
626    synchronized long nScriptGetVarJ(long id, int slot) {
627        validate();
628        return rsnScriptGetVarJ(mContext, id, slot);
629    }
630
631    native void rsnScriptSetVarF(long con, long id, int slot, float val);
632    synchronized void nScriptSetVarF(long id, int slot, float val) {
633        validate();
634        rsnScriptSetVarF(mContext, id, slot, val);
635    }
636    native float rsnScriptGetVarF(long con, long id, int slot);
637    synchronized float nScriptGetVarF(long id, int slot) {
638        validate();
639        return rsnScriptGetVarF(mContext, id, slot);
640    }
641    native void rsnScriptSetVarD(long con, long id, int slot, double val);
642    synchronized void nScriptSetVarD(long id, int slot, double val) {
643        validate();
644        rsnScriptSetVarD(mContext, id, slot, val);
645    }
646    native double rsnScriptGetVarD(long con, long id, int slot);
647    synchronized double nScriptGetVarD(long id, int slot) {
648        validate();
649        return rsnScriptGetVarD(mContext, id, slot);
650    }
651    native void rsnScriptSetVarV(long con, long id, int slot, byte[] val);
652    synchronized void nScriptSetVarV(long id, int slot, byte[] val) {
653        validate();
654        rsnScriptSetVarV(mContext, id, slot, val);
655    }
656    native void rsnScriptGetVarV(long con, long id, int slot, byte[] val);
657    synchronized void nScriptGetVarV(long id, int slot, byte[] val) {
658        validate();
659        rsnScriptGetVarV(mContext, id, slot, val);
660    }
661    native void rsnScriptSetVarVE(long con, long id, int slot, byte[] val,
662                                  long e, int[] dims);
663    synchronized void nScriptSetVarVE(long id, int slot, byte[] val,
664                                      long e, int[] dims) {
665        validate();
666        rsnScriptSetVarVE(mContext, id, slot, val, e, dims);
667    }
668    native void rsnScriptSetVarObj(long con, long id, int slot, long val);
669    synchronized void nScriptSetVarObj(long id, int slot, long val) {
670        validate();
671        rsnScriptSetVarObj(mContext, id, slot, val);
672    }
673
674    native long rsnScriptCCreate(long con, String resName, String cacheDir,
675                                 byte[] script, int length);
676    synchronized long nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
677        validate();
678        return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
679    }
680
681    native long rsnScriptIntrinsicCreate(long con, int id, long eid);
682    synchronized long nScriptIntrinsicCreate(int id, long eid) {
683        validate();
684        return rsnScriptIntrinsicCreate(mContext, id, eid);
685    }
686
687    native long  rsnScriptKernelIDCreate(long con, long sid, int slot, int sig);
688    synchronized long nScriptKernelIDCreate(long sid, int slot, int sig) {
689        validate();
690        return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
691    }
692
693    native long  rsnScriptFieldIDCreate(long con, long sid, int slot);
694    synchronized long nScriptFieldIDCreate(long sid, int slot) {
695        validate();
696        return rsnScriptFieldIDCreate(mContext, sid, slot);
697    }
698
699    native long rsnScriptGroupCreate(long con, long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types);
700    synchronized long nScriptGroupCreate(long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types) {
701        validate();
702        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
703    }
704
705    native void rsnScriptGroupSetInput(long con, long group, long kernel, long alloc);
706    synchronized void nScriptGroupSetInput(long group, long kernel, long alloc) {
707        validate();
708        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
709    }
710
711    native void rsnScriptGroupSetOutput(long con, long group, long kernel, long alloc);
712    synchronized void nScriptGroupSetOutput(long group, long kernel, long alloc) {
713        validate();
714        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
715    }
716
717    native void rsnScriptGroupExecute(long con, long group);
718    synchronized void nScriptGroupExecute(long group) {
719        validate();
720        rsnScriptGroupExecute(mContext, group);
721    }
722
723    native long  rsnSamplerCreate(long con, int magFilter, int minFilter,
724                                 int wrapS, int wrapT, int wrapR, float aniso);
725    synchronized long nSamplerCreate(int magFilter, int minFilter,
726                                 int wrapS, int wrapT, int wrapR, float aniso) {
727        validate();
728        return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
729    }
730
731    native long rsnProgramStoreCreate(long con, boolean r, boolean g, boolean b, boolean a,
732                                      boolean depthMask, boolean dither,
733                                      int srcMode, int dstMode, int depthFunc);
734    synchronized long nProgramStoreCreate(boolean r, boolean g, boolean b, boolean a,
735                                         boolean depthMask, boolean dither,
736                                         int srcMode, int dstMode, int depthFunc) {
737        validate();
738        return rsnProgramStoreCreate(mContext, r, g, b, a, depthMask, dither, srcMode,
739                                     dstMode, depthFunc);
740    }
741
742    native long rsnProgramRasterCreate(long con, boolean pointSprite, int cullMode);
743    synchronized long nProgramRasterCreate(boolean pointSprite, int cullMode) {
744        validate();
745        return rsnProgramRasterCreate(mContext, pointSprite, cullMode);
746    }
747
748    native void rsnProgramBindConstants(long con, long pv, int slot, long mID);
749    synchronized void nProgramBindConstants(long pv, int slot, long mID) {
750        validate();
751        rsnProgramBindConstants(mContext, pv, slot, mID);
752    }
753    native void rsnProgramBindTexture(long con, long vpf, int slot, long a);
754    synchronized void nProgramBindTexture(long vpf, int slot, long a) {
755        validate();
756        rsnProgramBindTexture(mContext, vpf, slot, a);
757    }
758    native void rsnProgramBindSampler(long con, long vpf, int slot, long s);
759    synchronized void nProgramBindSampler(long vpf, int slot, long s) {
760        validate();
761        rsnProgramBindSampler(mContext, vpf, slot, s);
762    }
763    native long rsnProgramFragmentCreate(long con, String shader, String[] texNames, long[] params);
764    synchronized long nProgramFragmentCreate(String shader, String[] texNames, long[] params) {
765        validate();
766        return rsnProgramFragmentCreate(mContext, shader, texNames, params);
767    }
768    native long rsnProgramVertexCreate(long con, String shader, String[] texNames, long[] params);
769    synchronized long nProgramVertexCreate(String shader, String[] texNames, long[] params) {
770        validate();
771        return rsnProgramVertexCreate(mContext, shader, texNames, params);
772    }
773
774    native long rsnMeshCreate(long con, long[] vtx, long[] idx, int[] prim);
775    synchronized long nMeshCreate(long[] vtx, long[] idx, int[] prim) {
776        validate();
777        return rsnMeshCreate(mContext, vtx, idx, prim);
778    }
779    native int  rsnMeshGetVertexBufferCount(long con, long id);
780    synchronized int nMeshGetVertexBufferCount(long id) {
781        validate();
782        return rsnMeshGetVertexBufferCount(mContext, id);
783    }
784    native int  rsnMeshGetIndexCount(long con, long id);
785    synchronized int nMeshGetIndexCount(long id) {
786        validate();
787        return rsnMeshGetIndexCount(mContext, id);
788    }
789    native void rsnMeshGetVertices(long con, long id, long[] vtxIds, int vtxIdCount);
790    synchronized void nMeshGetVertices(long id, long[] vtxIds, int vtxIdCount) {
791        validate();
792        rsnMeshGetVertices(mContext, id, vtxIds, vtxIdCount);
793    }
794    native void rsnMeshGetIndices(long con, long id, long[] idxIds, int[] primitives, int vtxIdCount);
795    synchronized void nMeshGetIndices(long id, long[] idxIds, int[] primitives, int vtxIdCount) {
796        validate();
797        rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
798    }
799
800    native long rsnPathCreate(long con, int prim, boolean isStatic, long vtx, long loop, float q);
801    synchronized long nPathCreate(int prim, boolean isStatic, long vtx, long loop, float q) {
802        validate();
803        return rsnPathCreate(mContext, prim, isStatic, vtx, loop, q);
804    }
805
806    long     mDev;
807    long     mContext;
808    @SuppressWarnings({"FieldCanBeLocal"})
809    MessageThread mMessageThread;
810
811    Element mElement_U8;
812    Element mElement_I8;
813    Element mElement_U16;
814    Element mElement_I16;
815    Element mElement_U32;
816    Element mElement_I32;
817    Element mElement_U64;
818    Element mElement_I64;
819    Element mElement_F32;
820    Element mElement_F64;
821    Element mElement_BOOLEAN;
822
823    Element mElement_ELEMENT;
824    Element mElement_TYPE;
825    Element mElement_ALLOCATION;
826    Element mElement_SAMPLER;
827    Element mElement_SCRIPT;
828    Element mElement_MESH;
829    Element mElement_PROGRAM_FRAGMENT;
830    Element mElement_PROGRAM_VERTEX;
831    Element mElement_PROGRAM_RASTER;
832    Element mElement_PROGRAM_STORE;
833    Element mElement_FONT;
834
835    Element mElement_A_8;
836    Element mElement_RGB_565;
837    Element mElement_RGB_888;
838    Element mElement_RGBA_5551;
839    Element mElement_RGBA_4444;
840    Element mElement_RGBA_8888;
841
842    Element mElement_FLOAT_2;
843    Element mElement_FLOAT_3;
844    Element mElement_FLOAT_4;
845
846    Element mElement_DOUBLE_2;
847    Element mElement_DOUBLE_3;
848    Element mElement_DOUBLE_4;
849
850    Element mElement_UCHAR_2;
851    Element mElement_UCHAR_3;
852    Element mElement_UCHAR_4;
853
854    Element mElement_CHAR_2;
855    Element mElement_CHAR_3;
856    Element mElement_CHAR_4;
857
858    Element mElement_USHORT_2;
859    Element mElement_USHORT_3;
860    Element mElement_USHORT_4;
861
862    Element mElement_SHORT_2;
863    Element mElement_SHORT_3;
864    Element mElement_SHORT_4;
865
866    Element mElement_UINT_2;
867    Element mElement_UINT_3;
868    Element mElement_UINT_4;
869
870    Element mElement_INT_2;
871    Element mElement_INT_3;
872    Element mElement_INT_4;
873
874    Element mElement_ULONG_2;
875    Element mElement_ULONG_3;
876    Element mElement_ULONG_4;
877
878    Element mElement_LONG_2;
879    Element mElement_LONG_3;
880    Element mElement_LONG_4;
881
882    Element mElement_YUV;
883
884    Element mElement_MATRIX_4X4;
885    Element mElement_MATRIX_3X3;
886    Element mElement_MATRIX_2X2;
887
888    Sampler mSampler_CLAMP_NEAREST;
889    Sampler mSampler_CLAMP_LINEAR;
890    Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
891    Sampler mSampler_WRAP_NEAREST;
892    Sampler mSampler_WRAP_LINEAR;
893    Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
894    Sampler mSampler_MIRRORED_REPEAT_NEAREST;
895    Sampler mSampler_MIRRORED_REPEAT_LINEAR;
896    Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
897
898    ProgramStore mProgramStore_BLEND_NONE_DEPTH_TEST;
899    ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
900    ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_TEST;
901    ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH;
902
903    ProgramRaster mProgramRaster_CULL_BACK;
904    ProgramRaster mProgramRaster_CULL_FRONT;
905    ProgramRaster mProgramRaster_CULL_NONE;
906
907    ///////////////////////////////////////////////////////////////////////////////////
908    //
909
910    /**
911     * The base class from which an application should derive in order
912     * to receive RS messages from scripts. When a script calls {@code
913     * rsSendToClient}, the data fields will be filled, and the run
914     * method will be called on a separate thread.  This will occur
915     * some time after {@code rsSendToClient} completes in the script,
916     * as {@code rsSendToClient} is asynchronous. Message handlers are
917     * not guaranteed to have completed when {@link
918     * android.renderscript.RenderScript#finish} returns.
919     *
920     */
921    public static class RSMessageHandler implements Runnable {
922        protected int[] mData;
923        protected int mID;
924        protected int mLength;
925        public void run() {
926        }
927    }
928    /**
929     * If an application is expecting messages, it should set this
930     * field to an instance of {@link RSMessageHandler}.  This
931     * instance will receive all the user messages sent from {@code
932     * sendToClient} by scripts from this context.
933     *
934     */
935    RSMessageHandler mMessageCallback = null;
936
937    public void setMessageHandler(RSMessageHandler msg) {
938        mMessageCallback = msg;
939    }
940    public RSMessageHandler getMessageHandler() {
941        return mMessageCallback;
942    }
943
944    /**
945     * Place a message into the message queue to be sent back to the message
946     * handler once all previous commands have been executed.
947     *
948     * @param id
949     * @param data
950     */
951    public void sendMessage(int id, int[] data) {
952        nContextSendMessage(id, data);
953    }
954
955    /**
956     * The runtime error handler base class.  An application should derive from this class
957     * if it wishes to install an error handler.  When errors occur at runtime,
958     * the fields in this class will be filled, and the run method will be called.
959     *
960     */
961    public static class RSErrorHandler implements Runnable {
962        protected String mErrorMessage;
963        protected int mErrorNum;
964        public void run() {
965        }
966    }
967
968    /**
969     * Application Error handler.  All runtime errors will be dispatched to the
970     * instance of RSAsyncError set here.  If this field is null a
971     * {@link RSRuntimeException} will instead be thrown with details about the error.
972     * This will cause program termaination.
973     *
974     */
975    RSErrorHandler mErrorCallback = null;
976
977    public void setErrorHandler(RSErrorHandler msg) {
978        mErrorCallback = msg;
979    }
980    public RSErrorHandler getErrorHandler() {
981        return mErrorCallback;
982    }
983
984    /**
985     * RenderScript worker thread priority enumeration.  The default value is
986     * NORMAL.  Applications wishing to do background processing should set
987     * their priority to LOW to avoid starving forground processes.
988     */
989    public enum Priority {
990        LOW (Process.THREAD_PRIORITY_BACKGROUND + (5 * Process.THREAD_PRIORITY_LESS_FAVORABLE)),
991        NORMAL (Process.THREAD_PRIORITY_DISPLAY);
992
993        int mID;
994        Priority(int id) {
995            mID = id;
996        }
997    }
998
999    void validateObject(BaseObj o) {
1000        if (o != null) {
1001            if (o.mRS != this) {
1002                throw new RSIllegalArgumentException("Attempting to use an object across contexts.");
1003            }
1004        }
1005    }
1006
1007    void validate() {
1008        if (mContext == 0) {
1009            throw new RSInvalidStateException("Calling RS with no Context active.");
1010        }
1011    }
1012
1013
1014    /**
1015     * Change the priority of the worker threads for this context.
1016     *
1017     * @param p New priority to be set.
1018     */
1019    public void setPriority(Priority p) {
1020        validate();
1021        nContextSetPriority(p.mID);
1022    }
1023
1024    static class MessageThread extends Thread {
1025        RenderScript mRS;
1026        boolean mRun = true;
1027        int[] mAuxData = new int[2];
1028
1029        static final int RS_MESSAGE_TO_CLIENT_NONE = 0;
1030        static final int RS_MESSAGE_TO_CLIENT_EXCEPTION = 1;
1031        static final int RS_MESSAGE_TO_CLIENT_RESIZE = 2;
1032        static final int RS_MESSAGE_TO_CLIENT_ERROR = 3;
1033        static final int RS_MESSAGE_TO_CLIENT_USER = 4;
1034        static final int RS_MESSAGE_TO_CLIENT_NEW_BUFFER = 5;
1035
1036        static final int RS_ERROR_FATAL_DEBUG = 0x0800;
1037        static final int RS_ERROR_FATAL_UNKNOWN = 0x1000;
1038
1039        MessageThread(RenderScript rs) {
1040            super("RSMessageThread");
1041            mRS = rs;
1042
1043        }
1044
1045        public void run() {
1046            // This function is a temporary solution.  The final solution will
1047            // used typed allocations where the message id is the type indicator.
1048            int[] rbuf = new int[16];
1049            mRS.nContextInitToClient(mRS.mContext);
1050            while(mRun) {
1051                rbuf[0] = 0;
1052                int msg = mRS.nContextPeekMessage(mRS.mContext, mAuxData);
1053                int size = mAuxData[1];
1054                int subID = mAuxData[0];
1055
1056                if (msg == RS_MESSAGE_TO_CLIENT_USER) {
1057                    if ((size>>2) >= rbuf.length) {
1058                        rbuf = new int[(size + 3) >> 2];
1059                    }
1060                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
1061                        RS_MESSAGE_TO_CLIENT_USER) {
1062                        throw new RSDriverException("Error processing message from RenderScript.");
1063                    }
1064
1065                    if(mRS.mMessageCallback != null) {
1066                        mRS.mMessageCallback.mData = rbuf;
1067                        mRS.mMessageCallback.mID = subID;
1068                        mRS.mMessageCallback.mLength = size;
1069                        mRS.mMessageCallback.run();
1070                    } else {
1071                        throw new RSInvalidStateException("Received a message from the script with no message handler installed.");
1072                    }
1073                    continue;
1074                }
1075
1076                if (msg == RS_MESSAGE_TO_CLIENT_ERROR) {
1077                    String e = mRS.nContextGetErrorMessage(mRS.mContext);
1078
1079                    // Throw RSRuntimeException under the following conditions:
1080                    //
1081                    // 1) It is an unknown fatal error.
1082                    // 2) It is a debug fatal error, and we are not in a
1083                    //    debug context.
1084                    // 3) It is a debug fatal error, and we do not have an
1085                    //    error callback.
1086                    if (subID >= RS_ERROR_FATAL_UNKNOWN ||
1087                        (subID >= RS_ERROR_FATAL_DEBUG &&
1088                         (mRS.mContextType != ContextType.DEBUG ||
1089                          mRS.mErrorCallback == null))) {
1090                        throw new RSRuntimeException("Fatal error " + subID + ", details: " + e);
1091                    }
1092
1093                    if(mRS.mErrorCallback != null) {
1094                        mRS.mErrorCallback.mErrorMessage = e;
1095                        mRS.mErrorCallback.mErrorNum = subID;
1096                        mRS.mErrorCallback.run();
1097                    } else {
1098                        android.util.Log.e(LOG_TAG, "non fatal RS error, " + e);
1099                        // Do not throw here. In these cases, we do not have
1100                        // a fatal error.
1101                    }
1102                    continue;
1103                }
1104
1105                if (msg == RS_MESSAGE_TO_CLIENT_NEW_BUFFER) {
1106                    Allocation.sendBufferNotification(subID);
1107                    continue;
1108                }
1109
1110                // 2: teardown.
1111                // But we want to avoid starving other threads during
1112                // teardown by yielding until the next line in the destructor
1113                // can execute to set mRun = false
1114                try {
1115                    sleep(1, 0);
1116                } catch(InterruptedException e) {
1117                }
1118            }
1119            //Log.d(LOG_TAG, "MessageThread exiting.");
1120        }
1121    }
1122
1123    RenderScript(Context ctx) {
1124        mContextType = ContextType.NORMAL;
1125        if (ctx != null) {
1126            mApplicationContext = ctx.getApplicationContext();
1127        }
1128        mRWLock = new ReentrantReadWriteLock();
1129    }
1130
1131    /**
1132     * Gets the application context associated with the RenderScript context.
1133     *
1134     * @return The application context.
1135     */
1136    public final Context getApplicationContext() {
1137        return mApplicationContext;
1138    }
1139
1140    /**
1141     * @hide
1142     */
1143    public static RenderScript create(Context ctx, int sdkVersion) {
1144        return create(ctx, sdkVersion, ContextType.NORMAL);
1145    }
1146
1147    /**
1148     * Create a RenderScript context.
1149     *
1150     * @hide
1151     * @param ctx The context.
1152     * @return RenderScript
1153     */
1154    public static RenderScript create(Context ctx, int sdkVersion, ContextType ct) {
1155        if (!sInitialized) {
1156            Log.e(LOG_TAG, "RenderScript.create() called when disabled; someone is likely to crash");
1157            return null;
1158        }
1159
1160        RenderScript rs = new RenderScript(ctx);
1161
1162        rs.mDev = rs.nDeviceCreate();
1163        rs.mContext = rs.nContextCreate(rs.mDev, 0, sdkVersion, ct.mID);
1164        rs.mContextType = ct;
1165        if (rs.mContext == 0) {
1166            throw new RSDriverException("Failed to create RS context.");
1167        }
1168        rs.mMessageThread = new MessageThread(rs);
1169        rs.mMessageThread.start();
1170        return rs;
1171    }
1172
1173    /**
1174     * Create a RenderScript context.
1175     *
1176     * @param ctx The context.
1177     * @return RenderScript
1178     */
1179    public static RenderScript create(Context ctx) {
1180        return create(ctx, ContextType.NORMAL);
1181    }
1182
1183    /**
1184     * Create a RenderScript context.
1185     *
1186     *
1187     * @param ctx The context.
1188     * @param ct The type of context to be created.
1189     * @return RenderScript
1190     */
1191    public static RenderScript create(Context ctx, ContextType ct) {
1192        int v = ctx.getApplicationInfo().targetSdkVersion;
1193        return create(ctx, v, ct);
1194    }
1195
1196    /**
1197     * Print the currently available debugging information about the state of
1198     * the RS context to the log.
1199     *
1200     */
1201    public void contextDump() {
1202        validate();
1203        nContextDump(0);
1204    }
1205
1206    /**
1207     * Wait for any pending asynchronous opeations (such as copies to a RS
1208     * allocation or RS script executions) to complete.
1209     *
1210     */
1211    public void finish() {
1212        nContextFinish();
1213    }
1214
1215    /**
1216     * Destroys this RenderScript context.  Once this function is called,
1217     * using this context or any objects belonging to this context is
1218     * illegal.
1219     *
1220     */
1221    public void destroy() {
1222        validate();
1223        nContextFinish();
1224
1225        nContextDeinitToClient(mContext);
1226        mMessageThread.mRun = false;
1227        try {
1228            mMessageThread.join();
1229        } catch(InterruptedException e) {
1230        }
1231
1232        nContextDestroy();
1233
1234        nDeviceDestroy(mDev);
1235        mDev = 0;
1236    }
1237
1238    boolean isAlive() {
1239        return mContext != 0;
1240    }
1241
1242    long safeID(BaseObj o) {
1243        if(o != null) {
1244            return o.getID(this);
1245        }
1246        return 0;
1247    }
1248}
1249