protected void cropImageAndSetWallpaper(
      Uri uri,
      OnBitmapCroppedHandler onBitmapCroppedHandler,
      final boolean finishActivityWhenDone) {
    // Get the crop
    boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;

    Point minDims = new Point();
    Point maxDims = new Point();
    Display d = getWindowManager().getDefaultDisplay();
    d.getCurrentSizeRange(minDims, maxDims);

    Point displaySize = new Point();
    d.getSize(displaySize);

    int maxDim = Math.max(maxDims.x, maxDims.y);
    final int minDim = Math.min(minDims.x, minDims.y);
    int defaultWallpaperWidth;
    if (isScreenLarge(getResources())) {
      defaultWallpaperWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
    } else {
      defaultWallpaperWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
    }

    boolean isPortrait = displaySize.x < displaySize.y;
    int portraitHeight;
    if (isPortrait) {
      portraitHeight = mCropView.getHeight();
    } else {
      // TODO: how to actually get the proper portrait height?
      // This is not quite right:
      portraitHeight = Math.max(maxDims.x, maxDims.y);
    }
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
      Point realSize = new Point();
      d.getRealSize(realSize);
      portraitHeight = Math.max(realSize.x, realSize.y);
    }
    // Get the crop
    RectF cropRect = mCropView.getCrop();
    int cropRotation = mCropView.getImageRotation();
    float cropScale = mCropView.getWidth() / (float) cropRect.width();

    Point inSize = mCropView.getSourceDimensions();
    Matrix rotateMatrix = new Matrix();
    rotateMatrix.setRotate(cropRotation);
    float[] rotatedInSize = new float[] {inSize.x, inSize.y};
    rotateMatrix.mapPoints(rotatedInSize);
    rotatedInSize[0] = Math.abs(rotatedInSize[0]);
    rotatedInSize[1] = Math.abs(rotatedInSize[1]);

    // ADJUST CROP WIDTH
    // Extend the crop all the way to the right, for parallax
    // (or all the way to the left, in RTL)
    float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
    // Cap the amount of extra width
    float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width();
    extraSpace = Math.min(extraSpace, maxExtraSpace);

    if (ltr) {
      cropRect.right += extraSpace;
    } else {
      cropRect.left -= extraSpace;
    }

    // ADJUST CROP HEIGHT
    if (isPortrait) {
      cropRect.bottom = cropRect.top + portraitHeight / cropScale;
    } else { // LANDSCAPE
      float extraPortraitHeight = portraitHeight / cropScale - cropRect.height();
      float expandHeight =
          Math.min(
              Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top), extraPortraitHeight / 2);
      cropRect.top -= expandHeight;
      cropRect.bottom += expandHeight;
    }
    final int outWidth = (int) Math.round(cropRect.width() * cropScale);
    final int outHeight = (int) Math.round(cropRect.height() * cropScale);

    Runnable onEndCrop =
        new Runnable() {
          public void run() {
            updateWallpaperDimensions(outWidth, outHeight);
            if (finishActivityWhenDone) {
              setResult(Activity.RESULT_OK);
              finish();
            }
          }
        };
    BitmapCropTask cropTask =
        new BitmapCropTask(
            this, uri, cropRect, cropRotation, outWidth, outHeight, true, false, onEndCrop);
    if (onBitmapCroppedHandler != null) {
      cropTask.setOnBitmapCropped(onBitmapCroppedHandler);
    }
    cropTask.execute();
  }