diff options
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r-- | src/com/android/launcher3/MainThreadExecutor.java | 80 | ||||
-rw-r--r-- | src/com/android/launcher3/WidgetPreviewLoader.java | 27 |
2 files changed, 104 insertions, 3 deletions
diff --git a/src/com/android/launcher3/MainThreadExecutor.java b/src/com/android/launcher3/MainThreadExecutor.java new file mode 100644 index 000000000..866b17c71 --- /dev/null +++ b/src/com/android/launcher3/MainThreadExecutor.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.launcher3; + +import android.os.Handler; +import android.os.Looper; + +import java.util.List; +import java.util.concurrent.AbstractExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * An executor service that executes its tasks on the main thread. + * + * Shutting down this executor is not supported. + */ +public class MainThreadExecutor extends AbstractExecutorService { + + private Handler mHandler = new Handler(Looper.getMainLooper()); + + @Override + public void execute(Runnable runnable) { + if (Looper.getMainLooper() == Looper.myLooper()) { + runnable.run(); + } else { + mHandler.post(runnable); + } + } + + /** + * Not supported and throws an exception when used. + */ + @Override + @Deprecated + public void shutdown() { + throw new UnsupportedOperationException(); + } + + /** + * Not supported and throws an exception when used. + */ + @Override + @Deprecated + public List<Runnable> shutdownNow() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isShutdown() { + return false; + } + + @Override + public boolean isTerminated() { + return false; + } + + /** + * Not supported and throws an exception when used. + */ + @Override + @Deprecated + public boolean awaitTermination(long l, TimeUnit timeUnit) throws InterruptedException { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index 36152f807..5dad2a860 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -35,6 +35,8 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; abstract class SoftReferenceThreadLocal<T> { private ThreadLocal<SoftReference<T>> mThreadLocal; @@ -137,6 +139,8 @@ public class WidgetPreviewLoader { private final ArrayList<SoftReference<Bitmap>> mUnusedBitmaps; private final static HashSet<String> sInvalidPackages; + private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor(); + static { sInvalidPackages = new HashSet<String>(); } @@ -492,7 +496,8 @@ public class WidgetPreviewLoader { Drawable drawable = null; if (previewImage != 0) { - drawable = mPackageManager.getDrawable(packageName, previewImage, null); + drawable = mutateOnMainThread( + mPackageManager.getDrawable(packageName, previewImage, null)); if (drawable == null) { Log.w(TAG, "Can't load widget preview drawable 0x" + Integer.toHexString(previewImage) + " for provider: " + provider); @@ -511,6 +516,7 @@ public class WidgetPreviewLoader { if (cellHSpan < 1) cellHSpan = 1; if (cellVSpan < 1) cellVSpan = 1; + // This Drawable is not directly drawn, so there's no need to mutate it. BitmapDrawable previewDrawable = (BitmapDrawable) mContext.getResources() .getDrawable(R.drawable.widget_tile); final int previewDrawableWidth = previewDrawable @@ -548,7 +554,7 @@ public class WidgetPreviewLoader { int yoffset = (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2); if (iconId > 0) - icon = mIconCache.getFullResIcon(packageName, iconId); + icon = mutateOnMainThread(mIconCache.getFullResIcon(packageName, iconId)); if (icon != null) { renderDrawableToBitmap(icon, defaultPreview, hoffset, yoffset, (int) (mAppIconSize * iconScale), @@ -617,7 +623,7 @@ public class WidgetPreviewLoader { c.setBitmap(null); } // Render the icon - Drawable icon = mIconCache.getFullResIcon(info); + Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info)); int paddingTop = mContext. getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top); @@ -677,4 +683,19 @@ public class WidgetPreviewLoader { } } + private Drawable mutateOnMainThread(final Drawable drawable) { + try { + return mMainThreadExecutor.submit(new Callable<Drawable>() { + @Override + public Drawable call() throws Exception { + return drawable.mutate(); + } + }).get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } } |