Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5cd24dc authored by Adrian Roos's avatar Adrian Roos Committed by Android (Google) Code Review
Browse files

Merge "Reload LockscreenWallpaper and ImageWallpaper on background thread" into nyc-dev

parents 3dd59487 7e9dec28
Loading
Loading
Loading
Loading
+91 −51
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.opengl.GLUtils;
import android.os.AsyncTask;
import android.os.SystemProperties;
import android.renderscript.Matrix4f;
import android.service.wallpaper.WallpaperService;
@@ -155,6 +156,8 @@ public class ImageWallpaper extends WallpaperService {

        private int mLastRequestedWidth = -1;
        private int mLastRequestedHeight = -1;
        private AsyncTask<Void, Void, Bitmap> mLoader;
        private boolean mNeedsDrawAfterLoadingWallpaper;

        public DrawableEngine() {
            super();
@@ -184,10 +187,9 @@ public class ImageWallpaper extends WallpaperService {
            super.onCreate(surfaceHolder);

            mDefaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();

            updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo());

            setOffsetNotificationsEnabled(false);

            updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo(), false /* forDraw */);
        }

        @Override
@@ -197,17 +199,19 @@ public class ImageWallpaper extends WallpaperService {
            mWallpaperManager.forgetLoadedWallpaper();
        }

        void updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo) {
        boolean updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo,
                boolean forDraw) {
            boolean hasWallpaper = true;

            // Load background image dimensions, if we haven't saved them yet
            if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
                // Need to load the image to get dimensions
                mWallpaperManager.forgetLoadedWallpaper();
                updateWallpaperLocked();
                if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
                    // Default to the display size if we can't find the dimensions
                    mBackgroundWidth = displayInfo.logicalWidth;
                    mBackgroundHeight = displayInfo.logicalHeight;
                loadWallpaper(forDraw);
                if (DEBUG) {
                    Log.d(TAG, "Reloading, redoing updateSurfaceSize later.");
                }
                hasWallpaper = false;
            }

            // Force the wallpaper to cover the screen in both dimensions
@@ -224,6 +228,7 @@ public class ImageWallpaper extends WallpaperService {
            } else {
                surfaceHolder.setSizeFromLayout();
            }
            return hasWallpaper;
        }

        @Override
@@ -299,6 +304,7 @@ public class ImageWallpaper extends WallpaperService {
            }
            super.onSurfaceRedrawNeeded(holder);

            mLastSurfaceHeight = mLastSurfaceWidth = -1;
            drawFrame();
        }

@@ -317,7 +323,9 @@ public class ImageWallpaper extends WallpaperService {
                // should change
                if (newRotation != mLastRotation) {
                    // Update surface size (if necessary)
                    updateSurfaceSize(getSurfaceHolder(), displayInfo);
                    if (!updateSurfaceSize(getSurfaceHolder(), displayInfo, true /* forDraw */)) {
                        return; // had to reload wallpaper, will retry later
                    }
                    mRotationAtLastSurfaceSizeUpdate = newRotation;
                    mDisplayWidthAtLastSurfaceSizeUpdate = displayInfo.logicalWidth;
                    mDisplayHeightAtLastSurfaceSizeUpdate = displayInfo.logicalHeight;
@@ -339,8 +347,8 @@ public class ImageWallpaper extends WallpaperService {
                }
                mLastRotation = newRotation;

                // Load bitmap if it is not yet loaded or if it was loaded at a different size
                if (mBackground == null || surfaceDimensionsChanged) {
                // Load bitmap if it is not yet loaded
                if (mBackground == null) {
                    if (DEBUG) {
                        Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
                                mBackground + ", " +
@@ -349,21 +357,12 @@ public class ImageWallpaper extends WallpaperService {
                                dw + ", " + dh);
                    }
                    mWallpaperManager.forgetLoadedWallpaper();
                    updateWallpaperLocked();
                    if (mBackground == null) {
                    loadWallpaper(true /* needDraw */);
                    if (DEBUG) {
                            Log.d(TAG, "Unable to load bitmap");
                        Log.d(TAG, "Reloading, resuming draw later");
                    }
                    return;
                }
                    if (DEBUG) {
                        if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
                            Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
                                    dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
                                    mBackground.getHeight());
                        }
                    }
                }

                // Center the scaled image
                mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(),
@@ -422,25 +421,32 @@ public class ImageWallpaper extends WallpaperService {
            }
        }

        private void updateWallpaperLocked() {
            Throwable exception = null;
        /**
         * Loads the wallpaper on background thread and schedules updating the surface frame,
         * and if {@param needsDraw} is set also draws a frame.
         *
         * If loading is already in-flight, subsequent loads are ignored (but needDraw is or-ed to
         * the active request).
         */
        private void loadWallpaper(boolean needsDraw) {
            mNeedsDrawAfterLoadingWallpaper |= needsDraw;
            if (mLoader != null) {
                if (DEBUG) {
                    Log.d(TAG, "Skipping loadWallpaper, already in flight ");
                }
                return;
            }
            mLoader = new AsyncTask<Void, Void, Bitmap>() {
                @Override
                protected Bitmap doInBackground(Void... params) {
                    Throwable exception;
                    try {
                mBackground = null;
                mBackgroundWidth = -1;
                mBackgroundHeight = -1;
                mBackground = mWallpaperManager.getBitmap();
                mBackgroundWidth = mBackground.getWidth();
                mBackgroundHeight = mBackground.getHeight();
            } catch (RuntimeException e) {
                exception = e;
            } catch (OutOfMemoryError e) {
                        return mWallpaperManager.getBitmap();
                    } catch (RuntimeException | OutOfMemoryError e) {
                        exception = e;
                    }

                    if (exception != null) {
                mBackground = null;
                mBackgroundWidth = -1;
                mBackgroundHeight = -1;
                        // Note that if we do fail at this, and the default wallpaper can't
                        // be loaded, we will go into a cycle.  Don't do a build where the
                        // default wallpaper can't be loaded.
@@ -451,7 +457,41 @@ public class ImageWallpaper extends WallpaperService {
                            // now we're really screwed.
                            Log.w(TAG, "Unable reset to default wallpaper!", ex);
                        }

                        try {
                            return mWallpaperManager.getBitmap();
                        } catch (RuntimeException | OutOfMemoryError e) {
                            Log.w(TAG, "Unable to load default wallpaper!", e);
                        }
                    }
                    return null;
                }

                @Override
                protected void onPostExecute(Bitmap b) {
                    mBackground = null;
                    mBackgroundWidth = -1;
                    mBackgroundHeight = -1;

                    if (b != null) {
                        mBackground = b;
                        mBackgroundWidth = mBackground.getWidth();
                        mBackgroundHeight = mBackground.getHeight();
                    }

                    if (DEBUG) {
                        Log.d(TAG, "Wallpaper loaded: " + mBackground);
                    }
                    updateSurfaceSize(getSurfaceHolder(), getDefaultDisplayInfo(),
                            false /* forDraw */);
                    if (mNeedsDrawAfterLoadingWallpaper) {
                        drawFrame();
                    }

                    mLoader = null;
                    mNeedsDrawAfterLoadingWallpaper = false;
                }
            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }

        @Override
+103 −55
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.DrawableWrapper;
import android.os.Bundle;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -46,9 +46,7 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen

    private static final String TAG = "LockscreenWallpaper";

    private final Context mContext;
    private final PhoneStatusBar mBar;
    private final IWallpaperManager mService;
    private final WallpaperManager mWallpaperManager;
    private final Handler mH;

@@ -58,68 +56,74 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
    // The user selected in the UI, or null if no user is selected or UI doesn't support selecting
    // users.
    private UserHandle mSelectedUser;
    private AsyncTask<Void, Void, LoaderResult> mLoader;

    public LockscreenWallpaper(Context ctx, PhoneStatusBar bar, Handler h) {
        mContext = ctx;
        mBar = bar;
        mH = h;
        mService = IWallpaperManager.Stub.asInterface(
                ServiceManager.getService(Context.WALLPAPER_SERVICE));
        mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE);
        mCurrentUserId = ActivityManager.getCurrentUser();

        IWallpaperManager service = IWallpaperManager.Stub.asInterface(
                ServiceManager.getService(Context.WALLPAPER_SERVICE));
        try {
            mService.setLockWallpaperCallback(this);
            service.setLockWallpaperCallback(this);
        } catch (RemoteException e) {
            Log.e(TAG, "System dead?" + e);
        }
    }

    public Bitmap getBitmap() {
        try {
        if (mCached) {
            return mCache;
        }
            if (!mService.isWallpaperSupported(mContext.getOpPackageName())) {
        if (!mWallpaperManager.isWallpaperSupported()) {
            mCached = true;
            mCache = null;
            return null;
        }

        LoaderResult result = loadBitmap(mCurrentUserId, mSelectedUser);
        if (result.success) {
            mCached = true;
            mCache = result.bitmap;
        }
        return mCache;
    }

    public LoaderResult loadBitmap(int currentUserId, UserHandle selectedUser) {
        // May be called on any thread - only use thread safe operations.

        // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK
        // wallpaper.
        final int lockWallpaperUserId =
                    mSelectedUser != null ? mSelectedUser.getIdentifier() : mCurrentUserId;
            ParcelFileDescriptor fd = mService.getWallpaper(null, WallpaperManager.FLAG_LOCK,
                    new Bundle(), lockWallpaperUserId);
                selectedUser != null ? selectedUser.getIdentifier() : currentUserId;
        ParcelFileDescriptor fd = mWallpaperManager.getWallpaperFile(
                WallpaperManager.FLAG_LOCK, lockWallpaperUserId);

        if (fd != null) {
            try {
                BitmapFactory.Options options = new BitmapFactory.Options();
                    mCache = BitmapFactory.decodeFileDescriptor(
                            fd.getFileDescriptor(), null, options);
                    mCached = true;
                    return mCache;
                return LoaderResult.success(BitmapFactory.decodeFileDescriptor(
                        fd.getFileDescriptor(), null, options));
            } catch (OutOfMemoryError e) {
                Log.w(TAG, "Can't decode file", e);
                    return null;
                return LoaderResult.fail();
            } finally {
                IoUtils.closeQuietly(fd);
            }
        } else {
                mCached = true;
                if (mSelectedUser != null && mSelectedUser.getIdentifier() != mCurrentUserId) {
            if (selectedUser != null && selectedUser.getIdentifier() != currentUserId) {
                // When selected user is different from the current user, show the selected
                // user's static wallpaper.
                    mCache = mWallpaperManager.getBitmapAsUser(mSelectedUser.getIdentifier());
                return LoaderResult.success(
                        mWallpaperManager.getBitmapAsUser(selectedUser.getIdentifier()));

            } else {
                // When there is no selected user, or it's same as the current user, show the
                // system (possibly dynamic) wallpaper for the selected user.
                    mCache = null;
                }
                return mCache;
                return LoaderResult.success(null);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "System dead?" + e);
            return null;
        }
    }

@@ -135,14 +139,16 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
            return;
        }
        mSelectedUser = selectedUser;

        mH.removeCallbacks(this);
        mH.post(this);
        postUpdateWallpaper();
    }

    @Override
    public void onWallpaperChanged() {
        // Called on Binder thread.
        postUpdateWallpaper();
    }

    private void postUpdateWallpaper() {
        mH.removeCallbacks(this);
        mH.post(this);
    }
@@ -150,10 +156,52 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
    @Override
    public void run() {
        // Called in response to onWallpaperChanged on the main thread.
        mCached = false;
        mCache = null;
        getBitmap();
        mBar.updateMediaMetaData(true /* metaDataChanged */, true /* allowEnterAnimation */);

        if (mLoader != null) {
            mLoader.cancel(false /* interrupt */);
        }

        final int currentUser = mCurrentUserId;
        final UserHandle selectedUser = mSelectedUser;
        mLoader = new AsyncTask<Void, Void, LoaderResult>() {
            @Override
            protected LoaderResult doInBackground(Void... params) {
                return loadBitmap(currentUser, selectedUser);
            }

            @Override
            protected void onPostExecute(LoaderResult result) {
                super.onPostExecute(result);
                if (isCancelled()) {
                    return;
                }
                if (result.success) {
                    mCached = true;
                    mCache = result.bitmap;
                    mBar.updateMediaMetaData(
                            true /* metaDataChanged */, true /* allowEnterAnimation */);
                }
                mLoader = null;
            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    private static class LoaderResult {
        public final boolean success;
        public final Bitmap bitmap;

        LoaderResult(boolean success, Bitmap bitmap) {
            this.success = success;
            this.bitmap = bitmap;
        }

        static LoaderResult success(Bitmap b) {
            return new LoaderResult(true, b);
        }

        static LoaderResult fail() {
            return new LoaderResult(false, null);
        }
    }

    /**