blob: 5c539b515277c42c53db2209dcc792ee901fcc28 [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
Bijan Amirzada41242f22014-03-21 12:12:18 -070017package com.android.browser;
John Reck3527dd12011-02-22 10:35:29 -080018
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
Bijan Amirzada41242f22014-03-21 12:12:18 -070037import com.android.browser.R;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080038
John Reck3527dd12011-02-22 10:35:29 -080039/**
40 * Handle setWallpaper requests
41 *
42 */
43public class WallpaperHandler extends Thread
44 implements OnMenuItemClickListener, DialogInterface.OnCancelListener {
45
John Reck3527dd12011-02-22 10:35:29 -080046 private static final String LOGTAG = "WallpaperHandler";
Ben Murdochb860a622011-02-21 18:40:02 +000047 // This should be large enough for BitmapFactory to decode the header so
48 // that we can mark and reset the input stream to avoid duplicate network i/o
49 private static final int BUFFER_SIZE = 128 * 1024;
John Reck3527dd12011-02-22 10:35:29 -080050
51 private Context mContext;
George Mount387d45d2011-10-07 15:57:53 -070052 private String mUrl;
John Reck3527dd12011-02-22 10:35:29 -080053 private ProgressDialog mWallpaperProgress;
54 private boolean mCanceled = false;
55
56 public WallpaperHandler(Context context, String url) {
57 mContext = context;
George Mount387d45d2011-10-07 15:57:53 -070058 mUrl = url;
John Reck3527dd12011-02-22 10:35:29 -080059 }
60
61 @Override
62 public void onCancel(DialogInterface dialog) {
63 mCanceled = true;
64 }
65
66 @Override
67 public boolean onMenuItemClick(MenuItem item) {
John Reck85493652011-06-10 15:14:23 -070068 if (mUrl != null && getState() == State.NEW) {
John Reck3527dd12011-02-22 10:35:29 -080069 // The user may have tried to set a image with a large file size as
70 // their background so it may take a few moments to perform the
71 // operation.
72 // Display a progress spinner while it is working.
73 mWallpaperProgress = new ProgressDialog(mContext);
74 mWallpaperProgress.setIndeterminate(true);
75 mWallpaperProgress.setMessage(mContext.getResources()
76 .getText(R.string.progress_dialog_setting_wallpaper));
77 mWallpaperProgress.setCancelable(true);
78 mWallpaperProgress.setOnCancelListener(this);
79 mWallpaperProgress.show();
80 start();
81 }
82 return true;
83 }
84
85 @Override
86 public void run() {
Ben Murdochb860a622011-02-21 18:40:02 +000087 WallpaperManager wm = WallpaperManager.getInstance(mContext);
88 Drawable oldWallpaper = wm.getDrawable();
89 InputStream inputstream = null;
John Reck3527dd12011-02-22 10:35:29 -080090 try {
91 // TODO: This will cause the resource to be downloaded again, when
92 // we should in most cases be able to grab it from the cache. To fix
93 // this we should query WebCore to see if we can access a cached
94 // version and instead open an input stream on that. This pattern
95 // could also be used in the download manager where the same problem
96 // exists.
George Mount387d45d2011-10-07 15:57:53 -070097 inputstream = openStream();
John Reck3527dd12011-02-22 10:35:29 -080098 if (inputstream != null) {
Ben Murdochb860a622011-02-21 18:40:02 +000099 if (!inputstream.markSupported()) {
100 inputstream = new BufferedInputStream(inputstream, BUFFER_SIZE);
101 }
102 inputstream.mark(BUFFER_SIZE);
103 BitmapFactory.Options options = new BitmapFactory.Options();
104 options.inJustDecodeBounds = true;
105 // We give decodeStream a wrapped input stream so it doesn't
106 // mess with our mark (currently it sets a mark of 1024)
107 BitmapFactory.decodeStream(
108 new BufferedInputStream(inputstream), null, options);
109 int maxWidth = wm.getDesiredMinimumWidth();
110 int maxHeight = wm.getDesiredMinimumHeight();
111 // Give maxWidth and maxHeight some leeway
112 maxWidth *= 1.25;
113 maxHeight *= 1.25;
114 int bmWidth = options.outWidth;
115 int bmHeight = options.outHeight;
116
117 int scale = 1;
George Mount387d45d2011-10-07 15:57:53 -0700118 while (bmWidth > maxWidth || bmHeight > maxHeight) {
Ben Murdochb860a622011-02-21 18:40:02 +0000119 scale <<= 1;
120 bmWidth >>= 1;
121 bmHeight >>= 1;
122 }
123 options.inJustDecodeBounds = false;
124 options.inSampleSize = scale;
125 try {
126 inputstream.reset();
127 } catch (IOException e) {
128 // BitmapFactory read more than we could buffer
129 // Re-open the stream
130 inputstream.close();
George Mount387d45d2011-10-07 15:57:53 -0700131 inputstream = openStream();
Ben Murdochb860a622011-02-21 18:40:02 +0000132 }
133 Bitmap scaledWallpaper = BitmapFactory.decodeStream(inputstream,
134 null, options);
Nils Holmström4db7e932012-04-26 18:46:23 +0200135 if (scaledWallpaper != null) {
136 wm.setBitmap(scaledWallpaper);
137 } else {
138 Log.e(LOGTAG, "Unable to set new wallpaper, " +
139 "decodeStream returned null.");
140 }
John Reck3527dd12011-02-22 10:35:29 -0800141 }
142 } catch (IOException e) {
143 Log.e(LOGTAG, "Unable to set new wallpaper");
144 // Act as though the user canceled the operation so we try to
145 // restore the old wallpaper.
146 mCanceled = true;
Ben Murdochb860a622011-02-21 18:40:02 +0000147 } finally {
148 if (inputstream != null) {
149 try {
150 inputstream.close();
151 } catch (IOException e) {
152 // Ignore
153 }
154 }
John Reck3527dd12011-02-22 10:35:29 -0800155 }
156
157 if (mCanceled) {
158 // Restore the old wallpaper if the user cancelled whilst we were
159 // setting
160 // the new wallpaper.
161 int width = oldWallpaper.getIntrinsicWidth();
162 int height = oldWallpaper.getIntrinsicHeight();
163 Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
164 Canvas canvas = new Canvas(bm);
165 oldWallpaper.setBounds(0, 0, width, height);
166 oldWallpaper.draw(canvas);
Dianne Hackborn43cfe8a2011-08-02 16:59:35 -0700167 canvas.setBitmap(null);
John Reck3527dd12011-02-22 10:35:29 -0800168 try {
Ben Murdochb860a622011-02-21 18:40:02 +0000169 wm.setBitmap(bm);
John Reck3527dd12011-02-22 10:35:29 -0800170 } catch (IOException e) {
171 Log.e(LOGTAG, "Unable to restore old wallpaper.");
172 }
173 mCanceled = false;
174 }
175
176 if (mWallpaperProgress.isShowing()) {
177 mWallpaperProgress.dismiss();
178 }
179 }
George Mount387d45d2011-10-07 15:57:53 -0700180
181 /**
182 * Opens the input stream for the URL that the class should
183 * use to set the wallpaper. Abstracts the difference between
184 * standard URLs and data URLs.
185 * @return An open InputStream for the data at the URL
186 * @throws IOException if there is an error opening the URL stream
187 * @throws MalformedURLException if the URL is malformed
188 */
189 private InputStream openStream() throws IOException, MalformedURLException {
190 InputStream inputStream = null;
191 if (DataUri.isDataUri(mUrl)) {
192 DataUri dataUri = new DataUri(mUrl);
193 inputStream = new ByteArrayInputStream(dataUri.getData());
194 } else {
195 URL url = new URL(mUrl);
196 inputStream = url.openStream();
197 }
198 return inputStream;
199 }
John Reck3527dd12011-02-22 10:35:29 -0800200}