WallpaperCropActivity.java revision 2a218b718e5f498a284341532178c84fe3850e63
1f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka/*
2f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Copyright (C) 2013 The Android Open Source Project
3f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka *
4f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License");
5f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * you may not use this file except in compliance with the License.
6f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * You may obtain a copy of the License at
7f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka *
8f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka *      http://www.apache.org/licenses/LICENSE-2.0
9f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka *
10f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Unless required by applicable law or agreed to in writing, software
11f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS,
12f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * See the License for the specific language governing permissions and
14f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * limitations under the License.
15f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka */
16f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
17f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkapackage com.android.launcher3;
18f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
19f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyalimport android.annotation.TargetApi;
20f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.app.ActionBar;
21f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.app.Activity;
22f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.app.WallpaperManager;
23f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.content.Context;
24f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.content.Intent;
25f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.content.SharedPreferences;
26f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.content.res.Configuration;
27f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.content.res.Resources;
282a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport android.graphics.Bitmap;
29f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.graphics.Matrix;
30f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.graphics.Point;
31f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.graphics.RectF;
32f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.net.Uri;
33f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyalimport android.os.Build;
34f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.os.Bundle;
352a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport android.os.Handler;
362a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport android.os.HandlerThread;
372a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport android.os.Message;
38f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.util.Log;
39f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.view.Display;
40f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.view.View;
41f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.view.WindowManager;
42f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.widget.Toast;
432a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
44f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyalimport com.android.gallery3d.common.BitmapCropTask;
45f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyalimport com.android.gallery3d.common.BitmapUtils;
46f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport com.android.gallery3d.common.Utils;
47f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport com.android.photos.BitmapRegionTileSource;
48f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport com.android.photos.BitmapRegionTileSource.BitmapSource;
492a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport com.android.photos.BitmapRegionTileSource.BitmapSource.InBitmapProvider;
502a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport com.android.photos.views.TiledImageRenderer.TileSource;
512a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
522a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport java.util.Collections;
532a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport java.util.Iterator;
542a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport java.util.Set;
552a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport java.util.WeakHashMap;
56f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
572a218b718e5f498a284341532178c84fe3850e63Sunny Goyalpublic class WallpaperCropActivity extends Activity implements Handler.Callback {
58f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    private static final String LOGTAG = "Launcher3.CropActivity";
59f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
60f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected static final String WALLPAPER_WIDTH_KEY = "wallpaper.width";
61f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height";
62f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal
63f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    /**
64f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka     * The maximum bitmap size we allow to be returned through the intent.
65f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka     * Intents have a maximum of 1MB in total size. However, the Bitmap seems to
66f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka     * have some overhead to hit so that we go way below the limit here to make
67f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka     * sure the intent stays below 1MB.We should consider just returning a byte
68f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka     * array instead of a Bitmap instance to avoid overhead.
69f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka     */
70f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    public static final int MAX_BMAP_IN_INTENT = 750000;
71f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal    public static final float WALLPAPER_SCREENS_SPAN = 2f;
72f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
732a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private static final int MSG_LOAD_IMAGE = 1;
742a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
75f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected CropView mCropView;
762a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    protected View mProgressView;
77f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected Uri mUri;
7812d9d42afb5bd750ab52e38cd66f6081f4bd76bfSelim Cinek    protected View mSetWallpaperButton;
79f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
802a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private HandlerThread mLoaderThread;
812a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private Handler mLoaderHandler;
822a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private LoadRequest mCurrentLoadRequest;
832a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private byte[] mTempStorageForDecoding = new byte[16 * 1024];
842a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    // A weak-set of reusable bitmaps
852a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private Set<Bitmap> mReusableBitmaps =
862a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            Collections.newSetFromMap(new WeakHashMap<Bitmap, Boolean>());
872a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
88f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    @Override
89f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected void onCreate(Bundle savedInstanceState) {
90f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        super.onCreate(savedInstanceState);
912a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
922a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mLoaderThread = new HandlerThread("wallpaper_loader");
932a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mLoaderThread.start();
942a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mLoaderHandler = new Handler(mLoaderThread.getLooper(), this);
952a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
96f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        init();
97f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (!enableRotation()) {
98f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            setRequestedOrientation(Configuration.ORIENTATION_PORTRAIT);
99f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
100f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
101f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
102f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected void init() {
103f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        setContentView(R.layout.wallpaper_cropper);
104f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
105f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        mCropView = (CropView) findViewById(R.id.cropView);
1062a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mProgressView = findViewById(R.id.loading);
107f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
108f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Intent cropIntent = getIntent();
109f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final Uri imageUri = cropIntent.getData();
110f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
111f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (imageUri == null) {
112f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            Log.e(LOGTAG, "No URI passed in intent, exiting WallpaperCropActivity");
113f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            finish();
114f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            return;
115f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
116f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
117f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Action bar
118f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Show the custom action bar view
119f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final ActionBar actionBar = getActionBar();
120f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        actionBar.setCustomView(R.layout.actionbar_set_wallpaper);
121f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        actionBar.getCustomView().setOnClickListener(
122f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                new View.OnClickListener() {
123f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    @Override
124f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    public void onClick(View v) {
125f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                        boolean finishActivityWhenDone = true;
126f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                        cropImageAndSetWallpaper(imageUri, null, finishActivityWhenDone);
127f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    }
128f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                });
129c192530433ab03c02462635e9ffbe3781b666e13Michael Jurka        mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
130f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
131f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Load image in background
132f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final BitmapRegionTileSource.UriBitmapSource bitmapSource =
133f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024);
13412d9d42afb5bd750ab52e38cd66f6081f4bd76bfSelim Cinek        mSetWallpaperButton.setEnabled(false);
135f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Runnable onLoad = new Runnable() {
136f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            public void run() {
137f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) {
138f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    Toast.makeText(WallpaperCropActivity.this,
139f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                            getString(R.string.wallpaper_load_fail),
140f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                            Toast.LENGTH_LONG).show();
141f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    finish();
142c192530433ab03c02462635e9ffbe3781b666e13Michael Jurka                } else {
14312d9d42afb5bd750ab52e38cd66f6081f4bd76bfSelim Cinek                    mSetWallpaperButton.setEnabled(true);
144f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
145f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
146f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        };
1472a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        setCropViewTileSource(bitmapSource, true, false, null, onLoad);
148f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
149f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
1501019588c3cbc255dc523161950adc22483777291Sunny Goyal    @Override
1511019588c3cbc255dc523161950adc22483777291Sunny Goyal    protected void onDestroy() {
1521019588c3cbc255dc523161950adc22483777291Sunny Goyal        if (mCropView != null) {
1531019588c3cbc255dc523161950adc22483777291Sunny Goyal            mCropView.destroy();
1541019588c3cbc255dc523161950adc22483777291Sunny Goyal        }
1552a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        if (mLoaderThread != null) {
1562a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            mLoaderThread.quit();
1572a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
1581019588c3cbc255dc523161950adc22483777291Sunny Goyal        super.onDestroy();
1591019588c3cbc255dc523161950adc22483777291Sunny Goyal    }
1601019588c3cbc255dc523161950adc22483777291Sunny Goyal
1612a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    /**
1622a218b718e5f498a284341532178c84fe3850e63Sunny Goyal     * This is called on {@link #mLoaderThread}
1632a218b718e5f498a284341532178c84fe3850e63Sunny Goyal     */
1642a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    @Override
1652a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    public boolean handleMessage(Message msg) {
1662a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        if (msg.what == MSG_LOAD_IMAGE) {
1672a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            final LoadRequest req = (LoadRequest) msg.obj;
1682a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            try {
1692a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                req.src.loadInBackground(new InBitmapProvider() {
1702a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
1712a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    @Override
1722a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    public Bitmap forPixelCount(int count) {
1732a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                        synchronized (mReusableBitmaps) {
1742a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                            Iterator<Bitmap> itr = mReusableBitmaps.iterator();
1752a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                            while (itr.hasNext()) {
1762a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                                Bitmap b = itr.next();
1772a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                                if (b.getWidth() * b.getHeight() >= count) {
1782a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                                    itr.remove();
1792a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                                    return b;
1802a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                                }
1812a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                            }
182d444a550ec1c8992fbac0a036b293fc4759d25c1Selim Cinek                        }
1832a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                        return null;
184d444a550ec1c8992fbac0a036b293fc4759d25c1Selim Cinek                    }
1852a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                });
1862a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            } catch (SecurityException securityException) {
1872a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                if (isDestroyed()) {
1882a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    // Temporarily granted permissions are revoked when the activity
1892a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    // finishes, potentially resulting in a SecurityException here.
1902a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    // Even though {@link #isDestroyed} might also return true in different
1912a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    // situations where the configuration changes, we are fine with
1922a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    // catching these cases here as well.
1932a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    return true;
1942a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                } else {
1952a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    // otherwise it had a different cause and we throw it further
1962a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    throw securityException;
197f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
198f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
1992a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2002a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            req.result = new BitmapRegionTileSource(this, req.src, mTempStorageForDecoding);
2012a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            runOnUiThread(new Runnable() {
2022a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2032a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                @Override
2042a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                public void run() {
2052a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    if (req == mCurrentLoadRequest) {
2062a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                        onLoadRequestComplete(req,
2072a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                                req.src.getLoadingState() == BitmapSource.State.LOADED);
2082a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    } else {
2092a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                        addReusableBitmap(req.result);
210f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    }
211f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
2122a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            });
2132a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            return true;
2142a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
2152a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        return false;
2162a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
2172a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2182a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private void addReusableBitmap(TileSource src) {
2192a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        synchronized (mReusableBitmaps) {
2202a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
2212a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    && src instanceof BitmapRegionTileSource) {
2222a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                Bitmap preview = ((BitmapRegionTileSource) src).getBitmap();
2232a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                if (preview != null && preview.isMutable()) {
2242a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    mReusableBitmaps.add(preview);
225f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
226f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
2272a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
2282a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
2292a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2302a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    protected void onLoadRequestComplete(LoadRequest req, boolean success) {
2312a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mCurrentLoadRequest = null;
2322a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        if (success) {
2332a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            TileSource oldSrc = mCropView.getTileSource();
2342a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            mCropView.setTileSource(req.result, null);
2352a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            mCropView.setTouchEnabled(req.touchEnabled);
2362a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            if (req.moveToLeft) {
2372a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                mCropView.moveToLeft();
2382a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            }
2392a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            if (req.scaleProvider != null) {
2402a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                mCropView.setScale(req.scaleProvider.getScale(req.result));
2412a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            }
2422a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2432a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            // Free last image
2442a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            if (oldSrc != null) {
2452a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                // Call yield instead of recycle, as we only want to free GL resource.
2462a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                // We can still reuse the bitmap for decoding any other image.
2472a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                oldSrc.getPreview().yield();
2482a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            }
2492a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            addReusableBitmap(oldSrc);
2502a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
2512a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        if (req.postExecute != null) {
2522a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            req.postExecute.run();
2532a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
2542a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
2552a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2562a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    public final void setCropViewTileSource(BitmapSource bitmapSource, boolean touchEnabled,
2572a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            boolean moveToLeft, CropViewScaleProvider scaleProvider, Runnable postExecute) {
2582a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        final LoadRequest req = new LoadRequest();
2592a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.moveToLeft = moveToLeft;
2602a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.src = bitmapSource;
2612a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.touchEnabled = touchEnabled;
2622a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.postExecute = postExecute;
2632a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.scaleProvider = scaleProvider;
2642a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mCurrentLoadRequest = req;
2652a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2662a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        // Remove any pending requests
2672a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mLoaderHandler.removeMessages(MSG_LOAD_IMAGE);
2682a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        Message.obtain(mLoaderHandler, MSG_LOAD_IMAGE, req).sendToTarget();
2692a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
270f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // We don't want to show the spinner every time we load an image, because that would be
271f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // annoying; instead, only start showing the spinner if loading the image has taken
272f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // longer than 1 sec (ie 1000 ms)
2732a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mProgressView.postDelayed(new Runnable() {
274f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            public void run() {
2752a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                if (mCurrentLoadRequest == req) {
2762a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    mProgressView.setVisibility(View.VISIBLE);
277f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
278f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
279f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }, 1000);
280f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
281f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
2822a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
283f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    public boolean enableRotation() {
284f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        return getResources().getBoolean(R.bool.allow_rotation);
285f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
286f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
287f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    public static String getSharedPreferencesKey() {
2888f82fb850ed00ceb769822dce56cce63fb33f291Helena Josol        return LauncherFiles.WALLPAPER_CROP_PREFERENCES_KEY;
289f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
290f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
291723f3b60d150ebda26849bc57493bfc7afc43cc7Sunny Goyal    protected void setWallpaper(Uri uri, final boolean finishActivityWhenDone) {
292f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal        int rotation = BitmapUtils.getRotationFromExif(this, uri);
293f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        BitmapCropTask cropTask = new BitmapCropTask(
294723f3b60d150ebda26849bc57493bfc7afc43cc7Sunny Goyal                this, uri, null, rotation, 0, 0, true, false, null);
295f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final Point bounds = cropTask.getImageBounds();
296f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Runnable onEndCrop = new Runnable() {
297f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            public void run() {
298f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                updateWallpaperDimensions(bounds.x, bounds.y);
299f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                if (finishActivityWhenDone) {
300f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    setResult(Activity.RESULT_OK);
301f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    finish();
302f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
303f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
304f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        };
305f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        cropTask.setOnEndRunnable(onEndCrop);
306f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        cropTask.setNoCrop(true);
307f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        cropTask.execute();
308f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
309f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
310f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected void cropImageAndSetWallpaper(
311f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            Resources res, int resId, final boolean finishActivityWhenDone) {
312f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // crop this image and scale it down to the default wallpaper size for
313f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // this device
314f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal        int rotation = BitmapUtils.getRotationFromExif(res, resId);
315f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Point inSize = mCropView.getSourceDimensions();
316f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal        Point outSize = BitmapUtils.getDefaultWallpaperSize(getResources(),
317f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                getWindowManager());
318f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal        RectF crop = Utils.getMaxCropRect(
319f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                inSize.x, inSize.y, outSize.x, outSize.y, false);
320f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Runnable onEndCrop = new Runnable() {
321f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            public void run() {
322f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                // Passing 0, 0 will cause launcher to revert to using the
323f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                // default wallpaper size
324f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                updateWallpaperDimensions(0, 0);
325f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                if (finishActivityWhenDone) {
326f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    setResult(Activity.RESULT_OK);
327f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    finish();
328f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
329f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
330f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        };
331f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        BitmapCropTask cropTask = new BitmapCropTask(this, res, resId,
332f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                crop, rotation, outSize.x, outSize.y, true, false, onEndCrop);
333f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        cropTask.execute();
334f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
335f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
336f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
337f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected void cropImageAndSetWallpaper(Uri uri,
338f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal            BitmapCropTask.OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) {
339942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka        boolean centerCrop = getResources().getBoolean(R.bool.center_crop);
340f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Get the crop
341f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
342f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
343f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Display d = getWindowManager().getDefaultDisplay();
344f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
345f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Point displaySize = new Point();
346f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        d.getSize(displaySize);
347f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        boolean isPortrait = displaySize.x < displaySize.y;
348f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
349f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal        Point defaultWallpaperSize = BitmapUtils.getDefaultWallpaperSize(getResources(),
350f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                getWindowManager());
351f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Get the crop
352f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        RectF cropRect = mCropView.getCrop();
353b24af13c8359963ecdea420a1b395149e7477f83Selim Cinek
354500dfeb109f614fd42e2cc383c5dcfecaa981b38Selim Cinek        Point inSize = mCropView.getSourceDimensions();
355500dfeb109f614fd42e2cc383c5dcfecaa981b38Selim Cinek
356f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        int cropRotation = mCropView.getImageRotation();
357f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        float cropScale = mCropView.getWidth() / (float) cropRect.width();
358f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
359500dfeb109f614fd42e2cc383c5dcfecaa981b38Selim Cinek
360f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Matrix rotateMatrix = new Matrix();
361f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        rotateMatrix.setRotate(cropRotation);
362f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        float[] rotatedInSize = new float[] { inSize.x, inSize.y };
363f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        rotateMatrix.mapPoints(rotatedInSize);
364f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        rotatedInSize[0] = Math.abs(rotatedInSize[0]);
365f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        rotatedInSize[1] = Math.abs(rotatedInSize[1]);
366f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
3671116efa8af024cb9fcae059c16e23caea984729fSelim Cinek
3681116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        // due to rounding errors in the cropview renderer the edges can be slightly offset
3691116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        // therefore we ensure that the boundaries are sanely defined
3701116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        cropRect.left = Math.max(0, cropRect.left);
3711116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        cropRect.right = Math.min(rotatedInSize[0], cropRect.right);
3721116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        cropRect.top = Math.max(0, cropRect.top);
3731116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        cropRect.bottom = Math.min(rotatedInSize[1], cropRect.bottom);
3741116efa8af024cb9fcae059c16e23caea984729fSelim Cinek
375f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // ADJUST CROP WIDTH
376f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Extend the crop all the way to the right, for parallax
377f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // (or all the way to the left, in RTL)
378942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka        float extraSpace;
379942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka        if (centerCrop) {
380942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka            extraSpace = 2f * Math.min(rotatedInSize[0] - cropRect.right, cropRect.left);
381942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka        } else {
382942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka            extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
383942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka        }
384f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Cap the amount of extra width
385f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        float maxExtraSpace = defaultWallpaperSize.x / cropScale - cropRect.width();
386f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        extraSpace = Math.min(extraSpace, maxExtraSpace);
387f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
388942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka        if (centerCrop) {
389942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka            cropRect.left -= extraSpace / 2f;
390942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka            cropRect.right += extraSpace / 2f;
391f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        } else {
392942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka            if (ltr) {
393942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka                cropRect.right += extraSpace;
394942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka            } else {
395942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka                cropRect.left -= extraSpace;
396942b9eefdc1a918ccc259a54bc61cb7fbfb03bfdMichael Jurka            }
397f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
398f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
399f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // ADJUST CROP HEIGHT
400f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (isPortrait) {
401f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            cropRect.bottom = cropRect.top + defaultWallpaperSize.y / cropScale;
402f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        } else { // LANDSCAPE
403f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            float extraPortraitHeight =
404f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    defaultWallpaperSize.y / cropScale - cropRect.height();
405f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            float expandHeight =
406f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top),
407f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                            extraPortraitHeight / 2);
408f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            cropRect.top -= expandHeight;
409f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            cropRect.bottom += expandHeight;
410f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
411f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final int outWidth = (int) Math.round(cropRect.width() * cropScale);
412f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final int outHeight = (int) Math.round(cropRect.height() * cropScale);
413f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
414f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Runnable onEndCrop = new Runnable() {
415f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            public void run() {
416f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                updateWallpaperDimensions(outWidth, outHeight);
417f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                if (finishActivityWhenDone) {
418f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    setResult(Activity.RESULT_OK);
419f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    finish();
420f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
421f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
422f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        };
423f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        BitmapCropTask cropTask = new BitmapCropTask(this, uri,
424f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                cropRect, cropRotation, outWidth, outHeight, true, false, onEndCrop);
425f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (onBitmapCroppedHandler != null) {
426f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            cropTask.setOnBitmapCropped(onBitmapCroppedHandler);
427f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
428f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        cropTask.execute();
429f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
430f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
431f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected void updateWallpaperDimensions(int width, int height) {
432f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        String spKey = getSharedPreferencesKey();
433f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
434f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        SharedPreferences.Editor editor = sp.edit();
435f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (width != 0 && height != 0) {
436f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            editor.putInt(WALLPAPER_WIDTH_KEY, width);
437f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            editor.putInt(WALLPAPER_HEIGHT_KEY, height);
438f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        } else {
439f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            editor.remove(WALLPAPER_WIDTH_KEY);
440f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            editor.remove(WALLPAPER_HEIGHT_KEY);
441f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
442f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        editor.commit();
443f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
444f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        suggestWallpaperDimension(getResources(),
445608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen                sp, getWindowManager(), WallpaperManager.getInstance(this), true);
446f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
447f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
448f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal    public static void suggestWallpaperDimension(Resources res,
449f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            final SharedPreferences sharedPrefs,
450f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            WindowManager windowManager,
451608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen            final WallpaperManager wallpaperManager, boolean fallBackToDefaults) {
452f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal        final Point defaultWallpaperSize = BitmapUtils.getDefaultWallpaperSize(res, windowManager);
453f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // If we have saved a wallpaper width/height, use that instead
454608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen
455608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen        int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, -1);
456608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen        int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, -1);
457608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen
458608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen        if (savedWidth == -1 || savedHeight == -1) {
459608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen            if (!fallBackToDefaults) {
460608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen                return;
461608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen            } else {
462608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen                savedWidth = defaultWallpaperSize.x;
463608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen                savedHeight = defaultWallpaperSize.y;
464608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen            }
465608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen        }
466608c0af2e8bcf5ee546b52097ce0184496a7c4a1Adam Cohen
467f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (savedWidth != wallpaperManager.getDesiredMinimumWidth() ||
468f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                savedHeight != wallpaperManager.getDesiredMinimumHeight()) {
469f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight);
470f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
471f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
4722a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
4732a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    static class LoadRequest {
4742a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        BitmapSource src;
4752a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        boolean touchEnabled;
4762a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        boolean moveToLeft;
4772a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        Runnable postExecute;
4782a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        CropViewScaleProvider scaleProvider;
4792a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
4802a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        TileSource result;
4812a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
4822a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
4832a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    interface CropViewScaleProvider {
4842a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        float getScale(TileSource src);
4852a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
486f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka}
487