blob: 0c60664efd9ee390a5fd6742a15077a2bc2356f6 [file] [log] [blame]
John Reck3527dd12011-02-22 10:35:29 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
19import android.app.ProgressDialog;
20import android.app.WallpaperManager;
21import android.content.Context;
22import android.content.DialogInterface;
23import android.graphics.Bitmap;
Ben Murdochb860a622011-02-21 18:40:02 +000024import android.graphics.BitmapFactory;
John Reck3527dd12011-02-22 10:35:29 -080025import android.graphics.Canvas;
26import android.graphics.drawable.Drawable;
27import android.util.Log;
28import android.view.MenuItem;
29import android.view.MenuItem.OnMenuItemClickListener;
Ben Murdochb860a622011-02-21 18:40:02 +000030import java.io.BufferedInputStream;
George Mount387d45d2011-10-07 15:57:53 -070031import java.io.ByteArrayInputStream;
John Reck3527dd12011-02-22 10:35:29 -080032import java.io.IOException;
33import java.io.InputStream;
34import java.net.MalformedURLException;
35import java.net.URL;
36
37/**
38 * Handle setWallpaper requests
39 *
40 */
41public class WallpaperHandler extends Thread
42 implements OnMenuItemClickListener, DialogInterface.OnCancelListener {
43
John Reck3527dd12011-02-22 10:35:29 -080044 private static final String LOGTAG = "WallpaperHandler";
Ben Murdochb860a622011-02-21 18:40:02 +000045 // This should be large enough for BitmapFactory to decode the header so
46 // that we can mark and reset the input stream to avoid duplicate network i/o
47 private static final int BUFFER_SIZE = 128 * 1024;
John Reck3527dd12011-02-22 10:35:29 -080048
49 private Context mContext;
George Mount387d45d2011-10-07 15:57:53 -070050 private String mUrl;
John Reck3527dd12011-02-22 10:35:29 -080051 private ProgressDialog mWallpaperProgress;
52 private boolean mCanceled = false;
53
54 public WallpaperHandler(Context context, String url) {
55 mContext = context;
George Mount387d45d2011-10-07 15:57:53 -070056 mUrl = url;
John Reck3527dd12011-02-22 10:35:29 -080057 }
58
59 @Override
60 public void onCancel(DialogInterface dialog) {
61 mCanceled = true;
62 }
63
64 @Override
65 public boolean onMenuItemClick(MenuItem item) {
John Reck85493652011-06-10 15:14:23 -070066 if (mUrl != null && getState() == State.NEW) {
John Reck3527dd12011-02-22 10:35:29 -080067 // The user may have tried to set a image with a large file size as
68 // their background so it may take a few moments to perform the
69 // operation.
70 // Display a progress spinner while it is working.
71 mWallpaperProgress = new ProgressDialog(mContext);
72 mWallpaperProgress.setIndeterminate(true);
73 mWallpaperProgress.setMessage(mContext.getResources()
74 .getText(R.string.progress_dialog_setting_wallpaper));
75 mWallpaperProgress.setCancelable(true);
76 mWallpaperProgress.setOnCancelListener(this);
77 mWallpaperProgress.show();
78 start();
79 }
80 return true;
81 }
82
83 @Override
84 public void run() {
Ben Murdochb860a622011-02-21 18:40:02 +000085 WallpaperManager wm = WallpaperManager.getInstance(mContext);
86 Drawable oldWallpaper = wm.getDrawable();
87 InputStream inputstream = null;
John Reck3527dd12011-02-22 10:35:29 -080088 try {
89 // TODO: This will cause the resource to be downloaded again, when
90 // we should in most cases be able to grab it from the cache. To fix
91 // this we should query WebCore to see if we can access a cached
92 // version and instead open an input stream on that. This pattern
93 // could also be used in the download manager where the same problem
94 // exists.
George Mount387d45d2011-10-07 15:57:53 -070095 inputstream = openStream();
John Reck3527dd12011-02-22 10:35:29 -080096 if (inputstream != null) {
Ben Murdochb860a622011-02-21 18:40:02 +000097 if (!inputstream.markSupported()) {
98 inputstream = new BufferedInputStream(inputstream, BUFFER_SIZE);
99 }
100 inputstream.mark(BUFFER_SIZE);
101 BitmapFactory.Options options = new BitmapFactory.Options();
102 options.inJustDecodeBounds = true;
103 // We give decodeStream a wrapped input stream so it doesn't
104 // mess with our mark (currently it sets a mark of 1024)
105 BitmapFactory.decodeStream(
106 new BufferedInputStream(inputstream), null, options);
107 int maxWidth = wm.getDesiredMinimumWidth();
108 int maxHeight = wm.getDesiredMinimumHeight();
109 // Give maxWidth and maxHeight some leeway
110 maxWidth *= 1.25;
111 maxHeight *= 1.25;
112 int bmWidth = options.outWidth;
113 int bmHeight = options.outHeight;
114
115 int scale = 1;
George Mount387d45d2011-10-07 15:57:53 -0700116 while (bmWidth > maxWidth || bmHeight > maxHeight) {
Ben Murdochb860a622011-02-21 18:40:02 +0000117 scale <<= 1;
118 bmWidth >>= 1;
119 bmHeight >>= 1;
120 }
121 options.inJustDecodeBounds = false;
122 options.inSampleSize = scale;
123 try {
124 inputstream.reset();
125 } catch (IOException e) {
126 // BitmapFactory read more than we could buffer
127 // Re-open the stream
128 inputstream.close();
George Mount387d45d2011-10-07 15:57:53 -0700129 inputstream = openStream();
Ben Murdochb860a622011-02-21 18:40:02 +0000130 }
131 Bitmap scaledWallpaper = BitmapFactory.decodeStream(inputstream,
132 null, options);
Nils Holmström4db7e932012-04-26 18:46:23 +0200133 if (scaledWallpaper != null) {
134 wm.setBitmap(scaledWallpaper);
135 } else {
136 Log.e(LOGTAG, "Unable to set new wallpaper, " +
137 "decodeStream returned null.");
138 }
John Reck3527dd12011-02-22 10:35:29 -0800139 }
140 } catch (IOException e) {
141 Log.e(LOGTAG, "Unable to set new wallpaper");
142 // Act as though the user canceled the operation so we try to
143 // restore the old wallpaper.
144 mCanceled = true;
Ben Murdochb860a622011-02-21 18:40:02 +0000145 } finally {
146 if (inputstream != null) {
147 try {
148 inputstream.close();
149 } catch (IOException e) {
150 // Ignore
151 }
152 }
John Reck3527dd12011-02-22 10:35:29 -0800153 }
154
155 if (mCanceled) {
156 // Restore the old wallpaper if the user cancelled whilst we were
157 // setting
158 // the new wallpaper.
159 int width = oldWallpaper.getIntrinsicWidth();
160 int height = oldWallpaper.getIntrinsicHeight();
161 Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
162 Canvas canvas = new Canvas(bm);
163 oldWallpaper.setBounds(0, 0, width, height);
164 oldWallpaper.draw(canvas);
Dianne Hackborn43cfe8a2011-08-02 16:59:35 -0700165 canvas.setBitmap(null);
John Reck3527dd12011-02-22 10:35:29 -0800166 try {
Ben Murdochb860a622011-02-21 18:40:02 +0000167 wm.setBitmap(bm);
John Reck3527dd12011-02-22 10:35:29 -0800168 } catch (IOException e) {
169 Log.e(LOGTAG, "Unable to restore old wallpaper.");
170 }
171 mCanceled = false;
172 }
173
174 if (mWallpaperProgress.isShowing()) {
175 mWallpaperProgress.dismiss();
176 }
177 }
George Mount387d45d2011-10-07 15:57:53 -0700178
179 /**
180 * Opens the input stream for the URL that the class should
181 * use to set the wallpaper. Abstracts the difference between
182 * standard URLs and data URLs.
183 * @return An open InputStream for the data at the URL
184 * @throws IOException if there is an error opening the URL stream
185 * @throws MalformedURLException if the URL is malformed
186 */
187 private InputStream openStream() throws IOException, MalformedURLException {
188 InputStream inputStream = null;
189 if (DataUri.isDataUri(mUrl)) {
190 DataUri dataUri = new DataUri(mUrl);
191 inputStream = new ByteArrayInputStream(dataUri.getData());
192 } else {
193 URL url = new URL(mUrl);
194 inputStream = url.openStream();
195 }
196 return inputStream;
197 }
John Reck3527dd12011-02-22 10:35:29 -0800198}