/*
   * TODO: Would be cleaner if this took an android.graphics.Rect instead, but that would require
   * a little more JNI magic.
   */
  public void endDrawing(int x, int y, int width, int height) {
    synchronized (getLayerController()) {
      try {
        updateViewport(!mUpdateViewportOnEndDraw);
        mUpdateViewportOnEndDraw = false;

        if (mTileLayer instanceof MultiTileLayer) {
          Rect rect = new Rect(x, y, x + width, y + height);
          ((MultiTileLayer) mTileLayer).invalidate(rect);
        }
      } finally {
        endTransaction(mTileLayer);
      }
    }
    Log.i(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - endDrawing");

    /* Used by robocop for testing purposes */
    if (mDrawListener != null) {
      mDrawListener.drawFinished(x, y, width, height);
    }
  }
  /**
   * This function is invoked by Gecko via JNI; be careful when modifying signature. The compositor
   * invokes this function on every frame to figure out what part of the page to display, and to
   * inform Java of the current display port. Since it is called on every frame, it needs to be
   * ultra-fast. It avoids taking any locks or allocating any objects. We keep around a
   * mCurrentViewTransform so we don't need to allocate a new ViewTransform everytime we're called.
   * NOTE: we might be able to return a ImmutableViewportMetrics which would avoid the copy into
   * mCurrentViewTransform.
   */
  public ViewTransform syncViewportInfo(
      int x, int y, int width, int height, float resolution, boolean layersUpdated) {
    // getViewportMetrics is thread safe so we don't need to synchronize.
    // We save the viewport metrics here, so we later use it later in
    // createFrame (which will be called by nsWindow::DrawWindowUnderlay on
    // the native side, by the compositor). The viewport
    // metrics can change between here and there, as it's accessed outside
    // of the compositor thread.
    mFrameMetrics = getViewportMetrics();

    mCurrentViewTransform.x = mFrameMetrics.viewportRectLeft;
    mCurrentViewTransform.y = mFrameMetrics.viewportRectTop;
    mCurrentViewTransform.scale = mFrameMetrics.zoomFactor;

    mRootLayer.setPositionAndResolution(x, y, x + width, y + height, resolution);

    if (layersUpdated && mRecordDrawTimes) {
      // If we got a layers update, that means a draw finished. Check to see if the area drawn
      // matches
      // one of our requested displayports; if it does calculate the draw time and notify the
      // DisplayPortCalculator
      DisplayPortMetrics drawn = new DisplayPortMetrics(x, y, x + width, y + height, resolution);
      long time = mDrawTimingQueue.findTimeFor(drawn);
      if (time >= 0) {
        long now = SystemClock.uptimeMillis();
        time = now - time;
        mRecordDrawTimes = DisplayPortCalculator.drawTimeUpdate(time, width * height);
      }
    }

    if (layersUpdated && mDrawListener != null) {
      /* Used by robocop for testing purposes */
      mDrawListener.drawFinished();
    }

    return mCurrentViewTransform;
  }