@Override
 public String run(Properties parms) {
   int wid = Integer.parseInt(parms.getProperty("wid"));
   int hei = Integer.parseInt(parms.getProperty("hei"));
   Log.d(TAG, ">>>>>>>run in doSetup wid = " + wid + " hei=" + hei);
   cameraView_.StopPreview();
   cameraView_.setupCamera(wid, hei, previewCb_);
   cameraView_.StartPreview();
   return "OK";
 }
 @Override
 public void onCameraReady() {
   if (initWebServer()) {
     int wid = cameraView_.Width();
     int hei = cameraView_.Height();
     cameraView_.StopPreview();
     cameraView_.setupCamera(wid, hei, previewCb_);
     cameraView_.StartPreview();
   }
 }
  private void initCamera() {
    SurfaceView cameraSurface = (SurfaceView) findViewById(R.id.surface_camera);
    cameraView_ = new CameraView(cameraSurface);
    cameraView_.setCameraReadyCallback(this);

    overlayView_ = (OverlayView) findViewById(R.id.surface_overlay);
    overlayView_.setOnTouchListener(this);
    overlayView_.setUpdateDoneCallback(this);
  }
 @Override
 public String run(Properties parms) {
   String ret = "";
   List<Camera.Size> supportSize = cameraView_.getSupportedPreviewSize();
   ret = ret + "" + cameraView_.Width() + "x" + cameraView_.Height() + "|";
   for (int i = 0; i < supportSize.size() - 1; i++) {
     ret = ret + "" + supportSize.get(i).width + "x" + supportSize.get(i).height + "|";
   }
   int i = supportSize.size() - 1;
   ret = ret + "" + supportSize.get(i).width + "x" + supportSize.get(i).height;
   JSONObject obj = new JSONObject();
   try {
     obj.put("camsize", ret);
     obj.put("quality", mQuality);
   } catch (JSONException e) {
     e.printStackTrace();
   }
   return obj.toString();
 }
        @Override
        public InputStream streaming(Properties parms) {
          VideoFrame targetFrame = null;
          for (int i = 0; i < maxVideoNumber; i++) {
            if (videoFrames[i].acquire()) {
              targetFrame = videoFrames[i];
              break;
            }
          }
          // return 503 internal error
          if (targetFrame == null) {
            Log.d(TAG, "No free videoFrame found!");
            return null;
          }

          // compress yuv to jpeg
          int picWidth = cameraView_.Width();
          int picHeight = cameraView_.Height();
          YuvImage newImage = new YuvImage(preFrame, ImageFormat.NV21, picWidth, picHeight, null);
          targetFrame.reset();
          boolean ret;
          inProcessing = true;
          try {
            ret =
                newImage.compressToJpeg(new Rect(0, 0, picWidth, picHeight), mQuality, targetFrame);
          } catch (Exception ex) {
            ret = false;
          }
          inProcessing = false;

          // compress success, return ok
          if (ret == true) {
            parms.setProperty("mime", "image/jpeg");
            InputStream ins = targetFrame.getInputStream();
            return ins;
          }
          // send 503 error
          targetFrame.release();

          return null;
        }
 @Override
 public String run(Properties parms) {
   int degree = Integer.parseInt(parms.getProperty("degree"));
   Log.d(TAG, ">>>>>>>run in doRotate degree = " + degree);
   cameraView_.StopPreview();
   cameraView_.Rotate(degree);
   cameraView_.setupCamera(cameraView_.Width(), cameraView_.Height(), previewCb_);
   cameraView_.StartPreview();
   return "OK";
 }
 @Override
 public String run(Properties parms) {
   Log.d(TAG, ">>>>>>>run in doAutoFocus");
   cameraView_.AutoFocus();
   return "OK";
 }
        public void onPreviewFrame(byte[] frame, Camera c) {
          if (!inProcessing) {
            inProcessing = true;

            int picWidth = cameraView_.Width();
            int picHeight = cameraView_.Height();
            ByteBuffer bbuffer = ByteBuffer.wrap(frame);
            try {
              bbuffer.get(preFrame, 0, picWidth * picHeight + picWidth * picHeight / 2);

              int numFilled = 0;

              int y = picHeight / 2;
              for (int i = 0; i < PIN_LENGTH; i++) {
                int x =
                    picWidth / 2 + (int) ((i + 0.5f - PIN_LENGTH / 2) * SYMBOL_SPACING * picWidth);
                int p = 0;
                // Take 4 nearby pixels, to filter out noise
                p += preFrame[picWidth * y + x] & 0xFF;
                p += preFrame[picWidth * y + x + 1] & 0xFF;
                p += preFrame[picWidth * (y + 1) + x] & 0xFF;
                p += preFrame[picWidth * (y + 1) + x + 1] & 0xFF;
                p /= 4;
                pinEntered[i] = (p < BRIGHTNESS_THRESHOLD);

                if (pinEntered[i]) numFilled++;
              }
              overlayView_.invalidate();

              if (System.currentTimeMillis() > delay) {
                delay = System.currentTimeMillis() + SEND_DELAY;

                if (sendEnter && numFilled == 0) {
                  sendEnter = false;
                  currentPin++;
                  runOnUiThread(
                      new Runnable() {
                        public void run() {
                          tvMessage2.setText("PIN: " + currentPin);
                        }
                      });
                }

                if (sendEnter && numFilled == PIN_LENGTH) {
                  final String[] cmd = {
                    "/system/bin/sh",
                    "-c",
                    "echo 'echo enter | "
                        + getFilesDir().getAbsolutePath()
                        + "/hid-gadget-test /dev/hidg0 keyboard' | su"
                  };
                  runOnUiThread(
                      new Runnable() {
                        public void run() {
                          tvMessage2.setText("PIN: " + currentPin + " - sending Enter");
                        }
                      });
                  Runtime.getRuntime().exec(cmd).waitFor();
                }

                if (!sendEnter && numFilled == PIN_LENGTH) {
                  sendEnter = true;
                }

                if (!sendEnter && numFilled < PIN_LENGTH) {
                  final int digit =
                      (currentPin / (int) Math.pow(10, PIN_LENGTH - numFilled - 1)) % 10;
                  final int pos = numFilled + 1;
                  final String[] cmd = {
                    "/system/bin/sh",
                    "-c",
                    "echo 'echo "
                        + digit
                        + " | "
                        + getFilesDir().getAbsolutePath()
                        + "/hid-gadget-test /dev/hidg0 keyboard' | su"
                  };
                  runOnUiThread(
                      new Runnable() {
                        public void run() {
                          tvMessage2.setText(
                              "PIN: "
                                  + String.format("%04d", currentPin)
                                  + " - sending digit #"
                                  + pos
                                  + " : "
                                  + digit);
                        }
                      });
                  Runtime.getRuntime().exec(cmd).waitFor();
                }
              }

            } catch (Exception e) {
              e.printStackTrace();
            }

            inProcessing = false;
          }
        }