public string queueAll()
            {
                var columns = new [] { KEY_CONTENT };
                Cursor cursor = sqLiteDatabase.query(MYDATABASE_TABLE, columns,
                  null, null, null, null, null);

                var result = new java.lang.StringBuilder();

                int index_CONTENT = cursor.getColumnIndex(KEY_CONTENT);
                for (cursor.moveToFirst(); !(cursor.isAfterLast()); cursor.moveToNext())
                {
                    result.append( cursor.getString(index_CONTENT)).append( "\n");
                }

                return result.ToAndroidString();
            }
        static ApplicationWebService_poll_onnfc()
        {
            // http://lifehacker.com/run-an-action-when-you-remove-your-phone-from-an-nfc-ta-1208446359
            // https://groups.google.com/forum/#!topic/android-developers/8-17f6ZLYJY

            //  enter ApplicationWebService { ManagedThreadId = 2029 }
            Console.WriteLine("enter ApplicationWebService_poll_onnfc " + new { Thread.CurrentThread.ManagedThreadId });

            // http://mobile.tutsplus.com/tutorials/android/reading-nfc-tags-with-android/
            // http://stackoverflow.com/questions/10848134/android-on-nfc-read-close-activity-not-the-main-activity
            // http://stackoverflow.com/questions/17989055/nfc-not-able-to-detect-a-tag
            // http://stackoverflow.com/questions/5685946/nfc-broadcastreceiver-problem

            var activity = ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext as ScriptCoreLib.Android.CoreAndroidWebServiceActivity;

            var adapter = android.nfc.NfcAdapter.getDefaultAdapter(
                activity
            );

            var isEnabled = adapter.isEnabled();

            Console.WriteLine(new { isEnabled });




            var intent = new Intent(
                activity,
                activity.GetType().ToClass()
                );

            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

            var pendingIntent = PendingIntent.getActivity(
                activity,
                0,
                intent,
                0
            );

            var filters = new IntentFilter[1];
            var techList = new[]
            { 
                //  [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.Ndef]
                //  dispatch tag: TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.NdefFormatable] message: null
                new [] { typeof(android.nfc.tech.MifareClassic).FullName },
                new [] { typeof(android.nfc.tech.NfcA).FullName},
                new [] { typeof(android.nfc.tech.Ndef).FullName},
                new [] { typeof(android.nfc.tech.NdefFormatable).FullName },

				// current javacards? (ISO 14443-4)
				new [] {     typeof(android.nfc.tech.IsoDep).FullName },
			};

            // http://124.16.139.131:24080/lxr/source/packages/apps/Nfc/src/com/android/nfc/NfcDispatcher.java?v=android-4.0.4


            //String[][] techList = new String[][] { new String[] { NfcA.class.getName(),
            //NfcB.class.getName(), NfcF.class.getName(),
            //NfcV.class.getName(), IsoDep.class.getName(),
            //MifareClassic.class.getName(),
            //MifareUltralight.class.getName(), Ndef.class.getName() } };



            // Notice that this is the same filter as in our manifest.
            filters[0] = new IntentFilter();

            // https://code.google.com/p/android/issues/detail?id=37673
            // http://www.xda-developers.com/android/activate-actions-upon-removal-of-nfc-tags/
            //filters[0].addAction(NfcAdapter.ACTION_TAG_LOST);

            // https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/core/java/android/nfc/NfcAdapter.java
            filters[0].addAction("android.nfc.action.TAG_LOST");

            filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
            filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
            filters[0].addAction(NfcAdapter.ACTION_TECH_DISCOVERED);


            filters[0].addCategory(Intent.CATEGORY_DEFAULT);

            //V:\src\AndroidNFCExperiment\ApplicationWebService.java:57: unreported exception android.content.IntentFilter.MalformedMimeTypeException; must be caught or declared to be thrown
            try
            {
                filters[0].addDataType("*/*");
            }
            catch
            {
                throw;
            }

            activity.AtNewIntent +=
                i =>
                {
                    var action = i.getAction();

                    Console.WriteLine("AtNewIntent " + new { action });

                    //I/System.Console(25300): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED }

                    if (action == NfcAdapter.ACTION_TECH_DISCOVERED)
                    {
                        //                    U:\src\AndroidNFCExperiment\ApplicationWebService___c__DisplayClass4.java:93: <identifier> expected
                        //private static Tag _<.cctor>b__0_Isinst_0064(Object _0064)
                        //                     ^

                        //                        I/System.Console(26970): AtPause
                        //D/NfcDispatcher(  747): Set Foreground Dispatch
                        //I/System.Console(26970): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED }
                        //I/System.Console(26970): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, tag =  }
                        //D/AndroidRuntime(26970): Shutting down VM
                        //W/dalvikvm(26970): threadid=1: thread exiting with uncaught exception (group=0x419dc700)
                        //I/ActivityManager(  440): START u0 {act=android.nfc.action.TECH_DISCOVERED flg=0x20000000 cmp=AndroidNFCExperiment.Activities/.ApplicationWebServiceActivity (has extras)} from pid -1
                        //W/ActivityManager(  440): startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x20000000 cmp=AndroidNFCExperiment.Activities/.ApplicationWebServiceActivity (has extras) }

                        //var tag = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

                        //Console.WriteLine("AtNewIntent " + new { action, tag });

                        // D/NfcDispatcher(  747): dispatch tag: TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.Ndef] 
                        // message: NdefMessage 
                        // [NdefRecord tnf=4 type=70696C65742E65653A656B616172743A32 payload=66195F26063133303130385904202020205F28033233335F2701316E1B5A13333038363439303039303030333032313336315304FDCCD727, 
                        //  NdefRecord tnf=1 type=536967 payload=01020080B489DEDA8C2271386B7962250063A7C7C8612C3D58C8CD44D674F9D1615E80C72D961F8AC822C3188D48EFC7DA9DA3FF5C306E1EF54E0610F66D1C891CC59428A27CAA4211D4040527CF9BCD16F20E0B3116966AFC2390B7EF30CCC877B8532281CA3CBE286D295AECEA4447FD62874872A46099D6CEED99ED6766B829FD3FDF800025687474703A2F2F70696C65742E65652F6372742F33303836343930302D303030312E637274
                        // ]



                        //                        I/ActivityManager(  440): START u0 {act=android.nfc.action.TECH_DISCOVERED flg=0x20000000 cmp=AndroidNFCExperiment.Activities/.ApplicationWebServiceActivity (has extras)} from pid -1
                        //W/ActivityManager(  440): startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x20000000 cmp=AndroidNFCExperiment.Activities/.ApplicationWebServiceActivity (has extras) }
                        //I/System.Console(30978): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED }
                        //I/NfcDispatcher(  747): matched TECH override
                        //I/System.Console(30978): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG }
                        //I/System.Console(30978): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.NdefFormatable], FullName = android.nfc.Tag }
                        //I/System.Console(30978): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.ID }
                        //I/System.Console(30978): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.ID, p = [B@4212cfc8, FullName = [B }
                        //I/System.Console(30978): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.ID, p = [B@4212cfc8, FullName = [B, HexString = fc4969f9 }
                        //I/System.Console(30978): AtResume

                        // https://groups.google.com/forum/#!topic/android-developers/8-17f6ZLYJY
                        //http://stackoverflow.com/questions/9009043/android-nfc-intercept-all-tags
                        var extras = i.getExtras();
                        var ks = extras.keySet();
                        var iterator = ks.iterator();
                        while (iterator.hasNext())
                        {
                            var current = (string)iterator.next();

                            Console.WriteLine("AtNewIntent " + new { action, current });



                            // I/System.Console(29237): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.Ndef], FullName = android.nfc.Tag }
                            // http://stackoverflow.com/questions/5968896/listing-all-extras-of-an-intent
                            extras.get(current).With(
                                p =>
                                {
                                    Console.WriteLine("AtNewIntent " + new { action, current, p, p.GetType().FullName });

                                    (p as Tag).With(
                                       tag =>
                                       {
                                           var id = (byte[])(object)tag.getId();

                                           Console.WriteLine("AtNewIntent " + new { action, current, id = id.ToHexString(), Thread.CurrentThread.ManagedThreadId });

                                           History.Add(
                                                id.ToHexString()
                                            );

                                           //I/System.Console(32331): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.Ndef], id = fdccd727, tech = android.nfc.tech.MifareClassic }
                                           //I/System.Console(32331): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.Ndef], id = fdccd727, tech = android.nfc.tech.NfcA }
                                           //I/System.Console(32331): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.Ndef], id = fdccd727, tech = android.nfc.tech.Ndef }

                                           //I/System.Console(32331): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.NdefFormatable], id = fc4969f9, tech = android.nfc.tech.MifareClassic }
                                           //I/System.Console(32331): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.NdefFormatable], id = fc4969f9, tech = android.nfc.tech.NfcA }
                                           //I/System.Console(32331): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.NdefFormatable], id = fc4969f9, tech = android.nfc.tech.NdefFormatable }

                                           tag.getTechList().WithEach(
                                               tech =>
                                               {
                                                   Console.WriteLine("AtNewIntent " + new { action, current, id = id.ToHexString(), tech });

                                                   if (tech == typeof(android.nfc.tech.MifareClassic).FullName)
                                                   {
                                                       android.nfc.tech.MifareClassic.get(tag).With(
                                                           m =>
                                                           {


                                                           }
                                                       );
                                                   }


                                                   if (tech == typeof(android.nfc.tech.NfcA).FullName)
                                                   {
                                                       android.nfc.tech.NfcA.get(tag).With(
                                                           m =>
                                                           {

                                                           }
                                                       );
                                                   }
                                               }
                                           );

                                           //tag.
                                       }
                                    );

                                    (p as byte[]).With(
                                        bytes =>
                                        {
                                            var HexString = bytes.ToHexString();

                                            Console.WriteLine("AtNewIntent " + new { action, current, p, p.GetType().FullName, HexString });
                                        }
                                    );

                                    // https://android.googlesource.com/platform/packages/apps/Nfc/+/android-4.2.1_r1.2/nci/src/com/android/nfc/dhimpl/NativeNfcTag.java

                                    //(p as android.os.Parcelable[]).With(
                                    //     m =>
                                    //     {

                                    //         Console.WriteLine("AtNewIntent " + new { action, current, records = m.getRecords().Length });

                                    //         m.getRecords().WithEach(
                                    //             r =>
                                    //             {
                                    //                 Console.WriteLine("AtNewIntent " + new { action, current, id = ((byte[])(object)r.getId()).ToHexString() });

                                    //             }
                                    //         );
                                    //     }
                                    // );
                                }
                            );

                        }

                        //                        I/System.Console(29527): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED }
                        //I/System.Console(29527): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG }
                        //I/System.Console(29527): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG, p = TAG: Tech [android.nfc.tech.MifareClassic, android.nfc.tech.NfcA, android.nfc.tech.Ndef], FullName = android.nfc.Tag }
                        //I/System.Console(29527): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.ID }
                        //I/System.Console(29527): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.ID, p = [B@42156c88, FullName = [B }
                        //I/System.Console(29527): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.NDEF_MESSAGES }
                        //I/System.Console(29527): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.NDEF_MESSAGES, p = [Landroid.os.Parcelable;@42156e98, FullName = [Landroid.os.Parcelable; }
                        //I/System.Console(29527): AtResume





                        //                        I/System.Console(28867): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED }
                        //I/System.Console(28867): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.TAG }
                        //I/System.Console(28867): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.ID }
                        //I/System.Console(28867): AtNewIntent { action = android.nfc.action.TECH_DISCOVERED, current = android.nfc.extra.NDEF_MESSAGES }




                        //var id = tag.getId();

                        //Console.WriteLine("AtNewIntent " + new { action, tag, id.Length, id = ((byte[])(object)id).ToHexString() });

                        //tag.getTechList().WithEach(
                        //    tech =>
                        //    {
                        //        Console.WriteLine("AtNewIntent " + new { action, tech });
                        //    }
                        //);
                        //tag.get
                    }
                };

            // who is using it?
            activity.AtResume +=
                delegate
                {
                    Console.WriteLine();
                    Console.WriteLine();
                    Console.WriteLine("AtResume");
                    Console.WriteLine();
                    adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
                };

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("before enableForegroundDispatch");
            adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);


            activity.AtPause +=
               delegate
               {
                   Console.WriteLine();
                   Console.WriteLine();
                   Console.WriteLine("AtPause");
                   adapter.disableForegroundDispatch(activity);
               };
        }
        // can we send a zip file?
        public static void Invoke(int index, Action<string> y, int frames = 4)
        {
            #region log
            var st = new Stopwatch();
            st.Start();
            Action<string> log =
                x =>
                {
                    var z = (st.Elapsed + " " + x);

                    Console.WriteLine(z);
                    y(z);
                };
            #endregion

            log("getting ready...");

            var DIRECTORY_DCIM = global::android.os.Environment.DIRECTORY_DCIM;

            var path = global::android.os.Environment.getExternalStoragePublicDirectory(DIRECTORY_DCIM).getAbsolutePath();
            path += "/Camera";

            //var n = DateTime.Now;
            //var f = new java.io.File(path + "/shot" + n.Ticks + ".jpg");

            var camera = default(android.hardware.Camera);
            var surface = default(SurfaceView);

            try
            {
                // PreviewCallbackWithBuffer { cc = 0, Length = 1048576 }
                // W/CameraService(   84): CameraService::connect X (pid 2117) rejected (existing client).

                log("android.hardware.Camera.open... " + new { index });

                camera = android.hardware.Camera.open(index);

                log("android.hardware.Camera.open... done ");

                var PreviewFormat = ImageFormat.UNKNOWN;

                #region setParameters
                var p = camera.getParameters();

                // The size of the buffer must match the values described above.
                // Gets the supported preview formats. NV21 is always supported.

                // http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getSupportedPreviewFormats()

                #region SupportedPictureFormat

                foreach (int SupportedPictureFormat in p.getSupportedPictureFormats().AsEnumerable())
                {
                    Console.WriteLine(new { SupportedPictureFormat });
                }

                //p.getSupportedPictureFormats().With(
                //     pformats =>
                //     {
                //         for (int i = 0; i < pformats.size(); i++)
                //         {
                //             var SupportedPictureFormat = (int)pformats.get(i);

                //             Console.WriteLine(new { SupportedPictureFormat });
                //         }
                //     }
                // );
                #endregion



                #region SupportedPreviewFormat

                foreach (int SupportedPreviewFormat in p.getSupportedPreviewFormats().AsEnumerable())
                {

                    if (SupportedPreviewFormat == ImageFormat.NV21)
                        PreviewFormat = SupportedPreviewFormat;
                    else if (PreviewFormat == ImageFormat.UNKNOWN)
                        PreviewFormat = SupportedPreviewFormat;

                    log("" + new { SupportedPreviewFormat });

                    Console.WriteLine(new { SupportedPreviewFormat });
                }
                //p.getSupportedPreviewFormats().With(
                //    pformats =>
                //    {
                //        for (int i = 0; i < pformats.size(); i++)
                //        {
                //            var SupportedPreviewFormat = (int)pformats.get(i);


                //            if (SupportedPreviewFormat == ImageFormat.NV21)
                //                PreviewFormat = SupportedPreviewFormat;
                //            else if (PreviewFormat == ImageFormat.UNKNOWN)
                //                PreviewFormat = SupportedPreviewFormat;

                //            log("" + new { SupportedPreviewFormat });
                //        }
                //    }
                //);
                #endregion


                //p.setPictureFormat(ImageFormat.YV12);

                p.setPreviewFormat(PreviewFormat);


                //D/DOMX    (  127): ERROR: failed check:(eError == OMX_ErrorNone) || (eError == OMX_ErrorNoMore) - returning error: 0x80001005 - Error returned from OMX API in ducati
                //E/CameraHAL(  127): Error while configuring rotation 0x80001005
                // http://questiontrack.com/galaxy-nexus-specificaly-camera-startpreview-failed-993603.html
                // http://stackoverflow.com/questions/16839869/orientation-error-causing-crash

                ////p.setRotation(0);

                #region getSupportedPreviewSizes
                //var s = p.getSupportedPreviewSizes();

                var min = default(android.hardware.Camera.Size);

                //for (int i = 0; i < s.size(); i++)
                foreach (android.hardware.Camera.Size size in p.getSupportedPreviewSizes().AsEnumerable())
                {
                    //var size = (android.hardware.Camera.Size)s.get(i);

                    //                I/System.Console( 6058): before takePicture { f = /mnt/sdcard/Pictures/shot.jpg }
                    //I/System.Console( 6058): { size = android.hardware.Camera$Size@4fde180 }

                    var SupportedPreviewSize = new { size.width, size.height };
                    log("" + new { SupportedPreviewSize });

                    if (min == null)
                        min = size;
                    else if (min.width > size.width)
                        min = size;

                }


                #endregion
                p.setPreviewSize(min.width, min.height);

                //For formats besides YV12, the size of the buffer is determined by multiplying the
                // preview image width, height, and bytes per pixel. The width and height can be read 
                // from getPreviewSize(). Bytes per pixel can be computed from getBitsPerPixel(int) / 8, 
                // using the image format from getPreviewFormat().

                //p.setPictureSize(min.width, min.height);


                // I/System.Console( 2860): { width = 640, height = 480, bytesperpixel = 0, buffersize = 0 }
                // the number of bits per pixel of the given format or -1 if the format doesn't exist or is not supported.
                //var bytesperpixel = (ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8);

                // http://stackoverflow.com/questions/13703596/mediacodec-and-camera-colorspaces-dont-match
                // https://code.google.com/p/android/issues/detail?id=37655

                var bitsperpixel = (ImageFormat.getBitsPerPixel(PreviewFormat));
                var buffersize = min.width * min.height / 8 * bitsperpixel;

                // 12
                // http://www.fourcc.org/yuv.php

                //var buffersize = 460800;

                log("" + new { min.width, min.height, bitsperpixel, buffersize });


                #region setFocusMode
                var focusModes = p.getSupportedFocusModes();
                var NextFocus = android.hardware.Camera.Parameters.FOCUS_MODE_FIXED;

                for (int i = 0; i < focusModes.size(); i++)
                {
                    var focusMode = (string)focusModes.get(i);

                    if (focusMode == android.hardware.Camera.Parameters.FOCUS_MODE_INFINITY)
                        NextFocus = android.hardware.Camera.Parameters.FOCUS_MODE_INFINITY;

                    System.Console.WriteLine(new { focusMode });
                }

                p.setFocusMode(NextFocus);
                #endregion

                camera.setParameters(p);
                #endregion


                // preview layout size: 736/1216
                buffersize = 1843200;

                // E/Camera-JNI( 3148): Manually set buffer was too small! Expected 460800 bytes, but got 307200!
                camera.addCallbackBuffer(new sbyte[buffersize]);
                camera.addCallbackBuffer(new sbyte[buffersize]);
                camera.addCallbackBuffer(new sbyte[buffersize]);
                camera.addCallbackBuffer(new sbyte[buffersize]);
                camera.addCallbackBuffer(new sbyte[buffersize]);

                var a = new EventWaitHandle(false, EventResetMode.ManualReset);

                // Task.ContinueWith
                // await

                (ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext as Activity).StartNew(
                    aa =>
                    {
                        log("at runOnUiThread...");


                        // solve issue with callback not being called: release the camera and try again. It usually works.
                        //To solve issue with rotation 0x80001005: restart app / service

                        // http://stackoverflow.com/questions/13546788/camera-takepicture-not-working-on-my-jb-gb-froyo-phones
                        aa.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);


                        #region setErrorCallback
                        camera.setErrorCallback(
                           new XErrorCallback
                           {
                               yield = (err, c) =>
                               {
                                   log("" + new { err });
                               }

                           }
                       );
                        #endregion

                        surface = new SurfaceView(ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext);

                        var holder = surface.getHolder();

                        // http://developer.android.com/reference/android/view/SurfaceHolder.html#SURFACE_TYPE_PUSH_BUFFERS
                        var SURFACE_TYPE_PUSH_BUFFERS = 0x00000003;
                        holder.setType(SURFACE_TYPE_PUSH_BUFFERS);




                        log("setPreviewCallbackWithBuffer");

                        var cc = 0;

                        //E/CameraHardwareSec(   84): int android::CameraHardwareSec::previewThread(): mSkipFrame(3) > 0
                        //E/CameraHardwareSec(   84): int android::CameraHardwareSec::previewThread(): mSkipFrame(2) > 0
                        //E/CameraHardwareSec(   84): int android::CameraHardwareSec::previewThread(): mSkipFrame(1) > 0

                        // http://stackoverflow.com/questions/16878042/camera-not-working-in-google-nexus-tablet

                        #region camera.PreviewCallbackWithBuffer
                        camera.PreviewCallbackWithBuffer(
                            (rawdata, c) =>
                            {
                                if (surface == null)
                                {
                                    // W/CameraHardwareSec(   84): virtual android::status_t android::CameraHardwareSec::cancelPicture() : not supported, just returning NO_ERROR
                                    return;
                                }

                                //                                                                   10080.0ms PreviewCallbackWithBuffer enter { cc = 58, Length = 460800 }
                                //10119.0ms PreviewCallbackWithBuffer compressToJpeg done { cc = 58, Elapsed = 39.0ms }
                                //10174.0ms PreviewCallbackWithBuffer ToBase64String done { cc = 58, Elapsed = 94.0ms }

                                var xcc = cc;

                                log("PreviewCallbackWithBuffer enter " + new { xcc, rawdata.Length });

                                // failed to flush { Length = 14619 }
                                //new Thread(
                                //    delegate()
                                {
                                    if (surface == null)
                                    {
                                        // W/CameraHardwareSec(   84): virtual android::status_t android::CameraHardwareSec::cancelPicture() : not supported, just returning NO_ERROR
                                        return;
                                    }

                                    var cst = new Stopwatch();
                                    cst.Start();

                                    // http://stackoverflow.com/questions/3426614/android-converting-from-nv21-preview-format-on-nexus-one-to-jpeg
                                    // http://developer.android.com/reference/android/graphics/YuvImage.html

                                    //Caused by: java.lang.IllegalArgumentException: only support ImageFormat.NV21 and ImageFormat.YUY2 for now
                                    //at android.graphics.YuvImage.<init>(YuvImage.java:82)


                                    // https://code.google.com/p/android/issues/detail?id=823
                                    // https://code.google.com/p/android-source-browsing/source/browse/graphics/java/android/graphics/YuvImage.java?repo=platform--frameworks--base&name=android-cts-4.1_r1
                                    var yuv = new YuvImage(
                                        rawdata,
                                        PreviewFormat,
                                        min.width,
                                        min.height,
                                        null
                                    );

                                    var m = new java.io.ByteArrayOutputStream();

                                    yuv.compressToJpeg(
                                        new Rect(0, 0, min.width, min.height),
                                        20,
                                        m);

                                    var data = (byte[])(object)m.toByteArray();

                                    log("PreviewCallbackWithBuffer compressToJpeg done " + new { xcc, cst.Elapsed });


                                    Console.WriteLine("compressToJpeg "
                                        + new { data.Length }
                                    );

                                    var src = "data:image/jpg;base64," +
                                            Convert.ToBase64String(
                                                data
                                            );

                                    log("PreviewCallbackWithBuffer ToBase64String done " + new { xcc, cst.Elapsed });

                                    y(src);


                                    //PreviewCallbackWithBuffer { cc = 0, Length = 1048576 }

                                    if (surface == null)
                                    {
                                        // W/CameraHardwareSec(   84): virtual android::status_t android::CameraHardwareSec::cancelPicture() : not supported, just returning NO_ERROR
                                        return;
                                    }

                                    //camera.addCallbackBuffer();
                                    camera.addCallbackBuffer(new sbyte[buffersize]);

                                    log("PreviewCallbackWithBuffer exit " + new { xcc, cst.Elapsed });


                                    if (xcc == frames)
                                    {

                                        //dummy.setVisibility(View.GONE);
                                        //dummy = null;

                                        // Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

                                        aa.StartNew(
                                                delegate
                                                {
                                                    if (surface != null)
                                                    {
                                                        surface.setVisibility(View.GONE);
                                                        surface = null;

                                                    }

                                                    a.Set();
                                                }
                                        );
                                    }
                                }
                                //).Start();

                                cc++;


                            }
                        );
                        #endregion


                        #region holder.surfaceChanged
                        holder.surfaceChanged(
                            delegate
                            {
                                log("surfaceChanged?");
                            }
                        );
                        #endregion

                        #region holder.surfaceCreated
                        holder.surfaceCreated(
                            delegate
                            {
                                log("surfaceCreated!");

                                // http://stackoverflow.com/questions/12098298/android-camera-app-passed-null-surface
                                // http://stackoverflow.com/questions/16945524/app-passed-null-surface-while-taking-a-picture-without-a-surfaceview

                                //  app passed NULL surface
                                log("before setPreviewDisplay, delay");

                                Thread.Sleep(400);

                                // https://code.google.com/p/zxing/source/browse/trunk/android/src/com/google/zxing/client/android/camera/CameraManager.java
                                // http://stackoverflow.com/questions/16945524/app-passed-null-surface-while-taking-a-picture-without-a-surfaceview

                                // http://stackoverflow.com/questions/4852740/surfaceview-getholder-not-returning-surfaceholder

                                log("before setPreviewDisplay " + new { holder });
                                // inside surface changed?

                                //if (surface == 0)
                                //{
                                //    LOGE("app passed NULL surface");
                                //    return NO_INIT;
                                //}

                                // https://android.googlesource.com/platform/frameworks/native/+/a6938bab1f6fa76ae98ebbe44f4e534e05fa0993/libs/ui/Camera.cpp
                                camera.setTryPreviewDisplay(holder);
                                log("after setPreviewDisplay");


                                log("startPreview, delay");
                                Thread.Sleep(200);
                                log("startPreview");

                                camera.startPreview();
                                log("after startPreview");
                            }
                        );
                        #endregion


                        #region addContentView
                        //surface.setBackgroundColor(Color.argb(0x0F, 255, 0, 0));

                        var pp = new android.widget.LinearLayout.LayoutParams(
                            android.widget.LinearLayout.LayoutParams.FILL_PARENT,
                            android.widget.LinearLayout.LayoutParams.FILL_PARENT
                            );
                        //pp.setMargins(64, 64, 64, 64);

                        aa.addContentView(surface, pp);
                        #endregion





                    }
                );

                a.WaitOne();

                log("PreviewCallbackWithBuffer done");

            }
            catch (Exception ex)
            {
                log("error: " + new { ex.Message, ex.StackTrace });

                throw new Exception("", ex);
            }
            finally
            {
                log("finally");
                // using
                if (camera != null)
                {
                    camera.stopPreview();
                    camera.release();
                    camera = null;
                }


            }
        }