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

Commit d023f9a9 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 24829 into eclair

* changes:
  Some optizations to wallpaper drawing/scrolling.
parents aa931bcb 19382ac1
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -24714,6 +24714,17 @@
 visibility="public"
>
</method>
<method name="getFastDrawable"
 return="android.graphics.drawable.Drawable"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getInstance"
 return="android.app.WallpaperManager"
 abstract="false"
@@ -24738,6 +24749,17 @@
 visibility="public"
>
</method>
<method name="peekFastDrawable"
 return="android.graphics.drawable.Drawable"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="setBitmap"
 return="void"
 abstract="false"
@@ -101558,6 +101580,17 @@
 visibility="protected"
>
</method>
<method name="quit"
 return="boolean"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
</class>
<interface name="IBinder"
 abstract="true"
+235 −42
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -56,9 +58,96 @@ public class WallpaperManager {
    
    private final Context mContext;
    
    /**
     * Special drawable that draws a wallpaper as fast as possible.  Assumes
     * no scaling or placement off (0,0) of the wallpaper (this should be done
     * at the time the bitmap is loaded).
     */
    static class FastBitmapDrawable extends Drawable {
        private final Bitmap mBitmap;
        private final int mWidth;
        private final int mHeight;
        private int mDrawLeft;
        private int mDrawTop;

        private FastBitmapDrawable(Bitmap bitmap) {
            mBitmap = bitmap;
            mWidth = bitmap.getWidth();
            mHeight = bitmap.getHeight();
            setBounds(0, 0, mWidth, mHeight);
        }

        @Override
        public void draw(Canvas canvas) {
            canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, null);
        }

        @Override
        public int getOpacity() {
            return PixelFormat.OPAQUE;
        }

        @Override
        public void setBounds(int left, int top, int right, int bottom) {
            mDrawLeft = left + (right-left - mWidth) / 2;
            mDrawTop = top + (bottom-top - mHeight) / 2;
        }

        @Override
        public void setBounds(Rect bounds) {
            // TODO Auto-generated method stub
            super.setBounds(bounds);
        }

        @Override
        public void setAlpha(int alpha) {
            throw new UnsupportedOperationException(
                    "Not supported with this drawable");
        }

        @Override
        public void setColorFilter(ColorFilter cf) {
            throw new UnsupportedOperationException(
                    "Not supported with this drawable");
        }

        @Override
        public void setDither(boolean dither) {
            throw new UnsupportedOperationException(
                    "Not supported with this drawable");
        }

        @Override
        public void setFilterBitmap(boolean filter) {
            throw new UnsupportedOperationException(
                    "Not supported with this drawable");
        }

        @Override
        public int getIntrinsicWidth() {
            return mWidth;
        }

        @Override
        public int getIntrinsicHeight() {
            return mHeight;
        }

        @Override
        public int getMinimumWidth() {
            return mWidth;
        }

        @Override
        public int getMinimumHeight() {
            return mHeight;
        }
    }
    
    static class Globals extends IWallpaperManagerCallback.Stub {
        private IWallpaperManager mService;
        private Bitmap mWallpaper;
        private Bitmap mDefaultWallpaper;
        
        private static final int MSG_CLEAR_WALLPAPER = 1;
        
@@ -74,6 +163,7 @@ public class WallpaperManager {
                        case MSG_CLEAR_WALLPAPER:
                            synchronized (this) {
                                mWallpaper = null;
                                mDefaultWallpaper = null;
                            }
                            break;
                    }
@@ -90,12 +180,19 @@ public class WallpaperManager {
            mHandler.sendEmptyMessage(MSG_CLEAR_WALLPAPER);
        }
        
        public Bitmap peekWallpaperBitmap(Context context) {
        public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) {
            synchronized (this) {
                if (mWallpaper != null) {
                    return mWallpaper;
                }
                if (mDefaultWallpaper != null) {
                    return mDefaultWallpaper;
                }
                mWallpaper = getCurrentWallpaperLocked(context);
                if (mWallpaper == null && returnDefault) {
                    mDefaultWallpaper = getDefaultWallpaperLocked(context);
                    return mDefaultWallpaper;
                }
                return mWallpaper;
            }
        }
@@ -134,48 +231,48 @@ public class WallpaperManager {
                        fd.close();
                    } catch (IOException e) {
                    }
                    if (bm == null) {
                        return bm;
                    }
                    bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
                    
                    // This is the final bitmap we want to return.
                    Bitmap newbm = Bitmap.createBitmap(width, height,
                            bm.getConfig());
                    newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
                    Canvas c = new Canvas(newbm);
                    c.setDensity(DisplayMetrics.DENSITY_DEVICE);
                    Rect targetRect = new Rect();
                    targetRect.left = targetRect.top = 0;
                    targetRect.right = bm.getWidth();
                    targetRect.bottom = bm.getHeight();
                    return generateBitmap(context, bm, width, height);
                }
            } catch (RemoteException e) {
            }
            return null;
        }
        
                    int deltaw = width - targetRect.right;
                    int deltah = height - targetRect.bottom;
        private Bitmap getDefaultWallpaperLocked(Context context) {
            try {
                InputStream is = context.getResources().openRawResource(
                        com.android.internal.R.drawable.default_wallpaper);
                if (is != null) {
                    int width = mService.getWidthHint();
                    int height = mService.getHeightHint();
                    
                    if (deltaw > 0 || deltah > 0) {
                        // We need to scale up so it covers the entire
                        // area.
                        float scale = 1.0f;
                        if (deltaw > deltah) {
                            scale = width / (float)targetRect.right;
                        } else {
                            scale = height / (float)targetRect.bottom;
                    if (width <= 0 || height <= 0) {
                        // Degenerate case: no size requested, just load
                        // bitmap as-is.
                        Bitmap bm = BitmapFactory.decodeStream(is, null, null);
                        try {
                            is.close();
                        } catch (IOException e) {
                        }
                        targetRect.right = (int)(targetRect.right*scale);
                        targetRect.bottom = (int)(targetRect.bottom*scale);
                        deltaw = width - targetRect.right;
                        deltah = height - targetRect.bottom;
                        if (bm != null) {
                            bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
                        }
                        return bm;
                    }
                    
                    targetRect.offset(deltaw/2, deltah/2);
                    Paint paint = new Paint();
                    paint.setFilterBitmap(true);
                    paint.setDither(true);
                    c.drawBitmap(bm, null, targetRect, paint);
                    // Load the bitmap with full color depth, to preserve
                    // quality for later processing.
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inDither = false;
                    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                    Bitmap bm = BitmapFactory.decodeStream(is, null, options);
                    try {
                        is.close();
                    } catch (IOException e) {
                    }
                    
                    bm.recycle();
                    return newbm;
                    return generateBitmap(context, bm, width, height);
                }
            } catch (RemoteException e) {
            }
@@ -219,9 +316,13 @@ public class WallpaperManager {
     * @return Returns a Drawable object that will draw the wallpaper.
     */
    public Drawable getDrawable() {
        Drawable dr = peekDrawable();
        return dr != null ? dr : Resources.getSystem().getDrawable(
                com.android.internal.R.drawable.default_wallpaper);
        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
        if (bm != null) {
            Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
            dr.setDither(false);
            return dr;
        }
        return null;
    }

    /**
@@ -234,8 +335,51 @@ public class WallpaperManager {
     * null pointer if these is none.
     */
    public Drawable peekDrawable() {
        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext);
        return bm != null ? new BitmapDrawable(mContext.getResources(), bm) : null;
        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
        if (bm != null) {
            Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
            dr.setDither(false);
            return dr;
        }
        return null;
    }

    /**
     * Like {@link #peekFastDrawable}, but always returns a valid Drawable.  If
     * no wallpaper is set, the system default wallpaper is returned.
     *
     * @return Returns a Drawable object that will draw the wallpaper.
     */
    public Drawable getFastDrawable() {
        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
        if (bm != null) {
            Drawable dr = new FastBitmapDrawable(bm);
            return dr;
        }
        return null;
    }

    /**
     * Like {@link #peekDrawable()}, but the returned Drawable has a number
     * of limitations to reduce its overhead as much as possible: it will
     * never scale the wallpaper (only centering it if the requested bounds
     * do match the bitmap bounds, which should not be typical), doesn't
     * allow setting an alpha, color filter, or other attributes, etc.  The
     * bounds of the returned drawable will be initialized to the same bounds
     * as the wallpaper, so normally you will not need to touch it.  The
     * drawable also assumes that it will be used in a context running in
     * the same density as the screen (not in density compatibility mode).
     *
     * @return Returns an optimized Drawable object that will draw the
     * wallpaper or a null pointer if these is none.
     */
    public Drawable peekFastDrawable() {
        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
        if (bm != null) {
            Drawable dr = new FastBitmapDrawable(bm);
            return dr;
        }
        return null;
    }

    /**
@@ -429,8 +573,10 @@ public class WallpaperManager {
     */
    public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
        try {
            //Log.v(TAG, "Sending new wallpaper offsets from app...");
            ViewRoot.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                    windowToken, xOffset, yOffset);
            //Log.v(TAG, "...app returning after sending offsets!");
        } catch (RemoteException e) {
            // Ignore.
        }
@@ -466,4 +612,51 @@ public class WallpaperManager {
    public void clear() throws IOException {
        setResource(com.android.internal.R.drawable.default_wallpaper);
    }
    
    static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
        if (bm == null) {
            return bm;
        }
        bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
        
        // This is the final bitmap we want to return.
        // XXX We should get the pixel depth from the system (to match the
        // physical display depth), when there is a way.
        Bitmap newbm = Bitmap.createBitmap(width, height,
                Bitmap.Config.RGB_565);
        newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
        Canvas c = new Canvas(newbm);
        c.setDensity(DisplayMetrics.DENSITY_DEVICE);
        Rect targetRect = new Rect();
        targetRect.left = targetRect.top = 0;
        targetRect.right = bm.getWidth();
        targetRect.bottom = bm.getHeight();
        
        int deltaw = width - targetRect.right;
        int deltah = height - targetRect.bottom;
        
        if (deltaw > 0 || deltah > 0) {
            // We need to scale up so it covers the entire
            // area.
            float scale = 1.0f;
            if (deltaw > deltah) {
                scale = width / (float)targetRect.right;
            } else {
                scale = height / (float)targetRect.bottom;
            }
            targetRect.right = (int)(targetRect.right*scale);
            targetRect.bottom = (int)(targetRect.bottom*scale);
            deltaw = width - targetRect.right;
            deltah = height - targetRect.bottom;
        }
        
        targetRect.offset(deltaw/2, deltah/2);
        Paint paint = new Paint();
        paint.setFilterBitmap(true);
        paint.setDither(true);
        c.drawBitmap(bm, null, targetRect, paint);
        
        bm.recycle();
        return newbm;
    }
}
+1 −3
Original line number Diff line number Diff line
@@ -22,8 +22,6 @@ import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.pm.ApplicationInfo;
import android.graphics.BitmapFactory;
import android.graphics.Movie;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
@@ -1699,7 +1697,7 @@ public class Resources {
                } else {
                    try {
                        InputStream is = mAssets.openNonAsset(
                                value.assetCookie, file, AssetManager.ACCESS_BUFFER);
                                value.assetCookie, file, AssetManager.ACCESS_STREAMING);
        //                System.out.println("Opened file " + file + ": " + is);
                        dr = Drawable.createFromResourceStream(this, value, is,
                                file, null);
+16 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ public class HandlerThread extends Thread {
    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason is isAlive() returns false, this method will return null. If this thread 
     * has been started, this method will blocked until the looper has been initialized.  
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
@@ -84,6 +84,21 @@ public class HandlerThread extends Thread {
        return mLooper;
    }
    
    /**
     * Ask the currently running looper to quit.  If the thread has not
     * been started or has finished (that is if {@link #getLooper} returns
     * null), then false is returned.  Otherwise the looper is asked to
     * quit and true is returned.
     */
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }
    
    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
+41 −2
Original line number Diff line number Diff line
@@ -28,9 +28,11 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.util.LogPrinter;
import android.view.Gravity;
import android.view.IWindowSession;
import android.view.MotionEvent;
@@ -74,6 +76,8 @@ public abstract class WallpaperService extends Service {
    private static final int MSG_WINDOW_RESIZED = 10030;
    private static final int MSG_TOUCH_EVENT = 10040;
    
    private Looper mCallbackLooper;
    
    /**
     * The actual implementation of a wallpaper.  A wallpaper service may
     * have multiple instances running (for example as a real wallpaper
@@ -120,6 +124,7 @@ public abstract class WallpaperService extends Service {
        boolean mOffsetMessageEnqueued;
        float mPendingXOffset;
        float mPendingYOffset;
        boolean mPendingSync;
        MotionEvent mPendingMove;
        
        final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -212,10 +217,14 @@ public abstract class WallpaperService extends Service {
            }

            @Override
            public void dispatchWallpaperOffsets(float x, float y) {
            public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
                synchronized (mLock) {
                    if (DEBUG) Log.v(TAG, "Dispatch wallpaper offsets: " + x + ", " + y);
                    mPendingXOffset = x;
                    mPendingYOffset = y;
                    if (sync) {
                        mPendingSync = true;
                    }
                    if (!mOffsetMessageEnqueued) {
                        mOffsetMessageEnqueued = true;
                        Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
@@ -551,9 +560,12 @@ public abstract class WallpaperService extends Service {
            
            float xOffset;
            float yOffset;
            boolean sync;
            synchronized (mLock) {
                xOffset = mPendingXOffset;
                yOffset = mPendingYOffset;
                sync = mPendingSync;
                mPendingSync = false;
                mOffsetMessageEnqueued = false;
            }
            if (DEBUG) Log.v(TAG, "Offsets change in " + this
@@ -563,6 +575,14 @@ public abstract class WallpaperService extends Service {
            final int availh = mIWallpaperEngine.mReqHeight-mCurHeight;
            final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
            onOffsetsChanged(xOffset, yOffset, xPixels, yPixels);
            
            if (sync) {
                try {
                    if (DEBUG) Log.v(TAG, "Reporting offsets change complete");
                    mSession.wallpaperOffsetsComplete(mWindow.asBinder());
                } catch (RemoteException e) {
                }
            }
        }
        
        void detach() {
@@ -622,7 +642,13 @@ public abstract class WallpaperService extends Service {
        IWallpaperEngineWrapper(WallpaperService context,
                IWallpaperConnection conn, IBinder windowToken,
                int windowType, boolean isPreview, int reqWidth, int reqHeight) {
            mCaller = new HandlerCaller(context, this);
            if (DEBUG && mCallbackLooper != null) {
                mCallbackLooper.setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
            }
            mCaller = new HandlerCaller(context,
                    mCallbackLooper != null
                            ? mCallbackLooper : context.getMainLooper(),
                    this);
            mConnection = conn;
            mWindowToken = windowToken;
            mWindowType = windowType;
@@ -736,5 +762,18 @@ public abstract class WallpaperService extends Service {
        return new IWallpaperServiceWrapper(this);
    }
    
    /**
     * This allows subclasses to change the thread that most callbacks
     * occur on.  Currently hidden because it is mostly needed for the
     * image wallpaper (which runs in the system process and doesn't want
     * to get stuck running on that seriously in use main thread).  Not
     * exposed right now because the semantics of this are not totally
     * well defined and some callbacks can still happen on the main thread).
     * @hide
     */
    public void setCallbackLooper(Looper looper) {
        mCallbackLooper = looper;
    }
    
    public abstract Engine onCreateEngine();
}
Loading