private void surfaceRender() {
    synchronized (this) {
      if (mLocalSurface == null
          || !mLocalSurface.isValid()
          || mBitmap == null
          || mByteBuffer == null) return;

      try {
        Canvas c = mLocalSurface.lockCanvas(null);
        mBitmap.copyPixelsFromBuffer(mByteBuffer);
        c.drawBitmap(mBitmap, 0, 0, null);
        mLocalSurface.unlockCanvasAndPost(c);
      } catch (Exception e) {
        Log.e("surfaceRender", e);
      }
    }
  }
      /** NOTE: This has to be called within a surface transaction. */
      public void drawIfNeeded() {
        synchronized (mWindowManagerService.mWindowMap) {
          if (!mInvalidated) {
            return;
          }
          mInvalidated = false;
          Canvas canvas = null;
          try {
            // Empty dirty rectangle means unspecified.
            if (mDirtyRect.isEmpty()) {
              mBounds.getBounds(mDirtyRect);
            }
            mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
            canvas = mSurface.lockCanvas(mDirtyRect);
            if (DEBUG_VIEWPORT_WINDOW) {
              Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect);
            }
          } catch (IllegalArgumentException iae) {
            /* ignore */
          } catch (Surface.OutOfResourcesException oore) {
            /* ignore */
          }
          if (canvas == null) {
            return;
          }
          if (DEBUG_VIEWPORT_WINDOW) {
            Slog.i(LOG_TAG, "Bounds: " + mBounds);
          }
          canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
          mPaint.setAlpha(mAlpha);
          Path path = mBounds.getBoundaryPath();
          canvas.drawPath(path, mPaint);

          mSurface.unlockCanvasAndPost(canvas);

          if (mAlpha > 0) {
            mSurfaceControl.show();
          } else {
            mSurfaceControl.hide();
          }
        }
      }
  private void manuallyPushImageToImageReader() {
    mImageReader = createImageReader();
    mImageReader.setOnImageAvailableListener(
        new ImageReader.OnImageAvailableListener() {
          @Override
          public void onImageAvailable(ImageReader reader) {
            Log.d(TAG, "NEW IMAGE AVAILABLE");

            DisplayMetrics metrics = getResources().getDisplayMetrics();

            Image image = reader.acquireLatestImage();
            printReaderFormat(image.getFormat());
            Log.d(TAG, "IMAGE FORMAT: " + image.getFormat());
            final Image.Plane[] planes = image.getPlanes();
            final ByteBuffer buffer = planes[0].getBuffer();
            int pixelStride = planes[0].getPixelStride();
            int rowStride = planes[0].getRowStride();
            int rowPadding = rowStride - pixelStride * mWidth;
            int w = mWidth + rowPadding / pixelStride;
            Bitmap bmp = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
            bmp.copyPixelsFromBuffer(buffer);
            mBmp = bmp;

            Thread t =
                new Thread(
                    new Runnable() {
                      @Override
                      public void run() {
                        try {
                          saveScreen(mBmp);
                        } catch (Exception e) {
                          e.printStackTrace();
                        }
                      }
                    });
            t.start();

            image.close();

            runOnUiThread(
                new Runnable() {
                  @Override
                  public void run() {
                    mImageView.setImageBitmap(mBmp);
                  }
                });

            /*
            Image img = reader.acquireLatestImage();
            Image.Plane[] planes = img.getPlanes();
            int width = img.getWidth();
            int height = img.getHeight();
            int pixelStride = planes[0].getPixelStride();
            int rowStride = planes[0].getRowStride();
            int rowPadding = rowStride - pixelStride * width;
            ByteBuffer buffer = planes[0].getBuffer();
            byte[] data = new byte[buffer.capacity()];
            buffer.get(data);

            for(int i = 10000; i < 100; i++){
                Log.d(TAG, getColourForInt(data[i]));
            }

            int offset = 0;
            Bitmap bitmap = Bitmap.createBitmap(metrics, width, height, Bitmap.Config.ARGB_8888);
            for (int i = 0; i < height; ++i) {
                for (int j = 0; j < width; ++j) {
                    int pixel = 0;
                    pixel |= (buffer.get(offset) & 0xff) << 16;     // R
                    pixel |= (buffer.get(offset + 1) & 0xff) << 8;  // G
                    pixel |= (buffer.get(offset + 2) & 0xff);       // B
                    pixel |= (buffer.get(offset + 3) & 0xff) << 24; // A
                    bitmap.setPixel(j, i, pixel);
                    offset += pixelStride;
                }
                offset += rowPadding;
            }
            mBmp = bitmap;
            img.close();

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mImageView.setImageBitmap(mBmp);
                }
            });
            */
          }
        },
        null);
    Surface surface = mImageReader.getSurface();
    if (surface == null) {
      Log.d(TAG, "SURFACE IS NULL");
    } else {
      Log.d(TAG, "SURFACE IS NOT NULL");
      Canvas canvas = surface.lockCanvas(null);

      int[] ints = new int[mWidth * mHeight];
      for (int i = 0; i < mWidth * mHeight; i++) {
        ints[i] = Color.MAGENTA; // 0x00FF0000;
      }

      // final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, ints.length);
      Bitmap bitmap = Bitmap.createBitmap(ints, mWidth, mHeight, Bitmap.Config.RGB_565);
      // canvas.drawARGB(255, 255, 0, 255);
      canvas.drawBitmap(bitmap, 0, 0, null);
      surface.unlockCanvasAndPost(canvas);
    }
  }