am d023f9a9: Merge change 24829 into eclair
Merge commit 'd023f9a9a90705410250cd86bc6446c738423a99' into eclair-plus-aosp * commit 'd023f9a9a90705410250cd86bc6446c738423a99': Some optizations to wallpaper drawing/scrolling.
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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 generateBitmap(context, bm, width, height);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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 (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) {
|
||||
}
|
||||
if (bm != null) {
|
||||
bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
|
||||
}
|
||||
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();
|
||||
|
||||
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;
|
||||
// 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) {
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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().
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -60,5 +60,5 @@ oneway interface IWindow {
|
||||
/**
|
||||
* Called for wallpaper windows when their offsets change.
|
||||
*/
|
||||
void dispatchWallpaperOffsets(float x, float y);
|
||||
void dispatchWallpaperOffsets(float x, float y, boolean sync);
|
||||
}
|
||||
|
||||
@@ -114,4 +114,6 @@ interface IWindowSession {
|
||||
* larger than the screen, set the offset within the screen.
|
||||
*/
|
||||
void setWallpaperPosition(IBinder windowToken, float x, float y);
|
||||
|
||||
void wallpaperOffsetsComplete(IBinder window);
|
||||
}
|
||||
|
||||
@@ -2868,7 +2868,13 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchWallpaperOffsets(float x, float y) {
|
||||
public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
|
||||
if (sync) {
|
||||
try {
|
||||
sWindowSession.wallpaperOffsetsComplete(asBinder());
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,13 @@ public class HandlerCaller {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public HandlerCaller(Context context, Looper looper, Callback callback) {
|
||||
mContext = context;
|
||||
mMainLooper = looper;
|
||||
mH = new MyHandler(mMainLooper);
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public SomeArgs obtainArgs() {
|
||||
synchronized (mH) {
|
||||
SomeArgs args = mArgsPool;
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.app.WallpaperManager;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Process;
|
||||
import android.service.wallpaper.WallpaperService;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
@@ -33,20 +35,29 @@ import android.content.BroadcastReceiver;
|
||||
*/
|
||||
public class ImageWallpaper extends WallpaperService {
|
||||
WallpaperManager mWallpaperManager;
|
||||
private HandlerThread mThread;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
|
||||
mThread = new HandlerThread("Wallpaper", Process.THREAD_PRIORITY_FOREGROUND);
|
||||
mThread.start();
|
||||
setCallbackLooper(mThread.getLooper());
|
||||
}
|
||||
|
||||
public Engine onCreateEngine() {
|
||||
return new DrawableEngine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mThread.quit();
|
||||
}
|
||||
|
||||
class DrawableEngine extends Engine {
|
||||
private final Object mLock = new Object();
|
||||
private final Rect mBounds = new Rect();
|
||||
private WallpaperObserver mReceiver;
|
||||
Drawable mBackground;
|
||||
float mXOffset;
|
||||
@@ -56,6 +67,9 @@ public class ImageWallpaper extends WallpaperService {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
updateWallpaper();
|
||||
drawFrame();
|
||||
// Assume we are the only one using the wallpaper in this
|
||||
// process, and force a GC now to release the old wallpaper.
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +81,6 @@ public class ImageWallpaper extends WallpaperService {
|
||||
registerReceiver(mReceiver, filter);
|
||||
updateWallpaper();
|
||||
surfaceHolder.setSizeFromLayout();
|
||||
//setTouchEventsEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,11 +150,7 @@ public class ImageWallpaper extends WallpaperService {
|
||||
|
||||
void updateWallpaper() {
|
||||
synchronized (mLock) {
|
||||
mBackground = mWallpaperManager.getDrawable();
|
||||
mBounds.left = mBounds.top = 0;
|
||||
mBounds.right = mBackground.getIntrinsicWidth();
|
||||
mBounds.bottom = mBackground.getIntrinsicHeight();
|
||||
mBackground.setBounds(mBounds);
|
||||
mBackground = mWallpaperManager.getFastDrawable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,12 @@ public class BaseIWindow extends IWindow.Stub {
|
||||
public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
|
||||
}
|
||||
|
||||
public void dispatchWallpaperOffsets(float x, float y) {
|
||||
public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
|
||||
if (sync) {
|
||||
try {
|
||||
mSession.wallpaperOffsetsComplete(asBinder());
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,6 +418,17 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
int mWallpaperAnimLayerAdjustment;
|
||||
float mLastWallpaperX;
|
||||
float mLastWallpaperY;
|
||||
// Lock for waiting for the wallpaper.
|
||||
final Object mWaitingOnWallpaperLock = new Object();
|
||||
// This is set when we are waiting for a wallpaper to tell us it is done
|
||||
// changing its scroll position.
|
||||
WindowState mWaitingOnWallpaper;
|
||||
// The last time we had a timeout when waiting for a wallpaper.
|
||||
long mLastWallpaperTimeoutTime;
|
||||
// We give a wallpaper up to 150ms to finish scrolling.
|
||||
static final long WALLPAPER_TIMEOUT = 150;
|
||||
// Time we wait after a timeout before trying to wait again.
|
||||
static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
|
||||
|
||||
AppWindowToken mFocusedApp = null;
|
||||
|
||||
@@ -1427,7 +1438,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
WindowState wallpaper = token.windows.get(curWallpaperIndex);
|
||||
|
||||
if (visible) {
|
||||
updateWallpaperOffsetLocked(wallpaper, dw, dh);
|
||||
updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
|
||||
}
|
||||
|
||||
// First, make sure the client has the current visibility
|
||||
@@ -1498,7 +1509,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh) {
|
||||
boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
|
||||
boolean sync) {
|
||||
boolean changed = false;
|
||||
boolean rawChanged = false;
|
||||
if (mLastWallpaperX >= 0) {
|
||||
@@ -1536,8 +1548,37 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if (DEBUG_WALLPAPER) Log.v(TAG, "Report new wp offset "
|
||||
+ wallpaperWin + " x=" + wallpaperWin.mWallpaperX
|
||||
+ " y=" + wallpaperWin.mWallpaperY);
|
||||
if (sync) {
|
||||
synchronized (mWaitingOnWallpaperLock) {
|
||||
mWaitingOnWallpaper = wallpaperWin;
|
||||
}
|
||||
}
|
||||
wallpaperWin.mClient.dispatchWallpaperOffsets(
|
||||
wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY);
|
||||
wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, sync);
|
||||
if (sync) {
|
||||
synchronized (mWaitingOnWallpaperLock) {
|
||||
if (mWaitingOnWallpaper != null) {
|
||||
long start = SystemClock.uptimeMillis();
|
||||
if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
|
||||
< start) {
|
||||
try {
|
||||
if (DEBUG_WALLPAPER) Log.v(TAG,
|
||||
"Waiting for offset complete...");
|
||||
mWaitingOnWallpaperLock.wait(WALLPAPER_TIMEOUT);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!");
|
||||
if ((start+WALLPAPER_TIMEOUT)
|
||||
< SystemClock.uptimeMillis()) {
|
||||
Log.i(TAG, "Timeout waiting for wallpaper to offset: "
|
||||
+ wallpaperWin);
|
||||
mLastWallpaperTimeoutTime = start;
|
||||
}
|
||||
}
|
||||
mWaitingOnWallpaper = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
@@ -1545,7 +1586,17 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
return changed;
|
||||
}
|
||||
|
||||
boolean updateWallpaperOffsetLocked() {
|
||||
void wallpaperOffsetsComplete(IBinder window) {
|
||||
synchronized (mWaitingOnWallpaperLock) {
|
||||
if (mWaitingOnWallpaper != null &&
|
||||
mWaitingOnWallpaper.mClient.asBinder() == window) {
|
||||
mWaitingOnWallpaper = null;
|
||||
mWaitingOnWallpaperLock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean updateWallpaperOffsetLocked(boolean sync) {
|
||||
final int dw = mDisplay.getWidth();
|
||||
final int dh = mDisplay.getHeight();
|
||||
|
||||
@@ -1563,9 +1614,11 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
while (curWallpaperIndex > 0) {
|
||||
curWallpaperIndex--;
|
||||
WindowState wallpaper = token.windows.get(curWallpaperIndex);
|
||||
if (updateWallpaperOffsetLocked(wallpaper, dw, dh)) {
|
||||
if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
|
||||
wallpaper.computeShownFrameLocked();
|
||||
changed = true;
|
||||
// We only want to be synchronous with one wallpaper.
|
||||
sync = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1595,7 +1648,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
curWallpaperIndex--;
|
||||
WindowState wallpaper = token.windows.get(curWallpaperIndex);
|
||||
if (visible) {
|
||||
updateWallpaperOffsetLocked(wallpaper, dw, dh);
|
||||
updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
|
||||
}
|
||||
|
||||
if (wallpaper.mWallpaperVisible != visible) {
|
||||
@@ -1782,8 +1835,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
imMayMove = false;
|
||||
} else {
|
||||
addWindowToListInOrderLocked(win, true);
|
||||
if (attrs.type == TYPE_WALLPAPER ||
|
||||
(attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
|
||||
if (attrs.type == TYPE_WALLPAPER) {
|
||||
mLastWallpaperTimeoutTime = 0;
|
||||
adjustWallpaperWindowsLocked();
|
||||
} else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
|
||||
adjustWallpaperWindowsLocked();
|
||||
}
|
||||
}
|
||||
@@ -1992,8 +2047,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
if (win.mAttrs.type == TYPE_WALLPAPER ||
|
||||
(win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
|
||||
if (win.mAttrs.type == TYPE_WALLPAPER) {
|
||||
mLastWallpaperTimeoutTime = 0;
|
||||
adjustWallpaperWindowsLocked();
|
||||
} else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
|
||||
adjustWallpaperWindowsLocked();
|
||||
}
|
||||
|
||||
@@ -2070,7 +2127,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
window.mWallpaperY = y;
|
||||
|
||||
if (mWallpaperTarget == window) {
|
||||
if (updateWallpaperOffsetLocked()) {
|
||||
if (updateWallpaperOffsetLocked(true)) {
|
||||
performLayoutAndPlaceSurfacesLocked();
|
||||
}
|
||||
}
|
||||
@@ -2258,7 +2315,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
performLayoutAndPlaceSurfacesLocked();
|
||||
if (displayed && win.mIsWallpaper) {
|
||||
updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
|
||||
mDisplay.getHeight());
|
||||
mDisplay.getHeight(), false);
|
||||
}
|
||||
if (win.mAppToken != null) {
|
||||
win.mAppToken.updateReportedVisibilityLocked();
|
||||
@@ -6303,6 +6360,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
public void wallpaperOffsetsComplete(IBinder window) {
|
||||
WindowManagerService.this.wallpaperOffsetsComplete(window);
|
||||
}
|
||||
|
||||
void windowAddedLocked() {
|
||||
if (mSurfaceSession == null) {
|
||||
if (localLOGV) Log.v(
|
||||
@@ -6698,7 +6759,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
|
||||
updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
|
||||
mDisplay.getHeight());
|
||||
mDisplay.getHeight(), false);
|
||||
}
|
||||
|
||||
if (localLOGV) {
|
||||
|
||||
@@ -1051,15 +1051,22 @@ public final class Bridge implements ILayoutBridge {
|
||||
// pass for now.
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setInsets(IWindow window, int touchable, Rect contentInsets,
|
||||
Rect visibleInsets) {
|
||||
// pass for now.
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setWallpaperPosition(IBinder window, float x, float y) {
|
||||
// pass for now.
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void wallpaperOffsetsComplete(IBinder window) {
|
||||
// pass for now.
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
// pass for now.
|
||||
return null;
|
||||
@@ -1114,7 +1121,7 @@ public final class Bridge implements ILayoutBridge {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void dispatchWallpaperOffsets(float x, float y) {
|
||||
public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
|
||||
// pass for now.
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user