Bug 816547: Make sure the Bitmap is accessed in UI thread in LWTheme. [r=mfinkle]

--HG--
extra : rebase_source : 7f99818a2395fdc4f03b24927f706a4f81197038
This commit is contained in:
Sriram Ramasubramanian 2013-02-26 11:42:24 -08:00
Родитель a8e0a1a69c
Коммит 2560db822a
1 изменённых файлов: 74 добавлений и 77 удалений

Просмотреть файл

@ -18,13 +18,17 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Build;
import android.os.Looper;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewParent;
import java.net.URL;
import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
@ -34,15 +38,13 @@ public class LightweightTheme implements GeckoEventListener {
private static final String LOGTAG = "GeckoLightweightTheme";
private Application mApplication;
private Handler mHandler;
private Bitmap mBitmap;
private int mColor;
private boolean mIsLight;
public static interface OnChangeListener {
// This is the View's default post.
// This is required to post the change/rest on UI thread.
public boolean post(Runnable action);
// The View should change its background/text color.
public void onLightweightThemeChanged();
@ -54,8 +56,10 @@ public class LightweightTheme implements GeckoEventListener {
public LightweightTheme(Application application) {
mApplication = application;
mHandler = new Handler(Looper.getMainLooper());
mListeners = new ArrayList<OnChangeListener>();
// unregister isn't needed as the lifetime is same as the application.
GeckoAppShell.getEventDispatcher().registerEventListener("LightweightTheme:Update", this);
GeckoAppShell.getEventDispatcher().registerEventListener("LightweightTheme:Disable", this);
}
@ -70,15 +74,50 @@ public class LightweightTheme implements GeckoEventListener {
mListeners.remove(listener);
}
public void setLightweightTheme(String headerURL) {
@Override
public void handleMessage(String event, JSONObject message) {
try {
if (event.equals("LightweightTheme:Update")) {
JSONObject lightweightTheme = message.getJSONObject("data");
String headerURL = lightweightTheme.getString("headerURL");
int mark = headerURL.indexOf('?');
if (mark != -1)
headerURL = headerURL.substring(0, mark);
try {
// Get the image and convert it to a bitmap.
URL url = new URL(headerURL);
InputStream stream = url.openStream();
mBitmap = BitmapFactory.decodeStream(stream);
final Bitmap bitmap = BitmapFactory.decodeStream(stream);
stream.close();
mHandler.post(new Runnable() {
public void run() {
setLightweightTheme(bitmap);
}
});
} catch(MalformedURLException e) {
} catch(IOException e) {
}
} else if (event.equals("LightweightTheme:Disable")) {
mHandler.post(new Runnable() {
public void run() {
resetLightweightTheme();
}
});
}
} catch (Exception e) {
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
}
}
// The download could be HTTP for previews, so let's be sure we have a bitmap
/**
* Set a new lightweight theme with the given bitmap.
* Note: This should be called on the UI thread to restrict accessing the
* bitmap to a single thread.
*
* @param bitmap The bitmap used for the lightweight theme.
*/
private void setLightweightTheme(Bitmap bitmap) {
mBitmap = bitmap;
if (mBitmap == null || mBitmap.getWidth() == 0 || mBitmap.getHeight() == 0) {
mBitmap = null;
return;
@ -98,66 +137,24 @@ public class LightweightTheme implements GeckoEventListener {
(0.0721 * (mColor &0x000000FF));
mIsLight = (luminance > 110) ? true : false;
notifyListeners();
} catch(java.net.MalformedURLException e) {
mBitmap = null;
} catch(java.io.IOException e) {
mBitmap = null;
}
for (OnChangeListener listener : mListeners)
listener.onLightweightThemeChanged();
}
public void resetLightweightTheme() {
/**
* Reset the lightweight theme.
* Note: This should be called on the UI thread to restrict accessing the
* bitmap to a single thread.
*/
private void resetLightweightTheme() {
if (mBitmap != null) {
// Reset the bitmap.
mBitmap = null;
// Post the reset on the UI thread.
for (OnChangeListener listener : mListeners) {
final OnChangeListener oneListener = listener;
oneListener.post(new Runnable() {
@Override
public void run() {
oneListener.onLightweightThemeReset();
}
});
for (OnChangeListener listener : mListeners)
listener.onLightweightThemeReset();
}
}
}
public void notifyListeners() {
if (mBitmap == null)
return;
// Post the change on the UI thread.
for (OnChangeListener listener : mListeners) {
final OnChangeListener oneListener = listener;
oneListener.post(new Runnable() {
@Override
public void run() {
oneListener.onLightweightThemeChanged();
}
});
}
}
@Override
public void handleMessage(String event, JSONObject message) {
try {
if (event.equals("LightweightTheme:Update")) {
JSONObject lightweightTheme = message.getJSONObject("data");
String headerURL = lightweightTheme.getString("headerURL");
int mark = headerURL.indexOf('?');
if (mark != -1)
headerURL = headerURL.substring(0, mark);
setLightweightTheme(headerURL);
} else if (event.equals("LightweightTheme:Disable")) {
resetLightweightTheme();
}
} catch (Exception e) {
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
}
}
/**
* A lightweight theme is enabled only if there is an active bitmap.