diff options
Diffstat (limited to 'core')
17 files changed, 825 insertions, 66 deletions
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index 8ac9557..7e71088 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -514,12 +514,12 @@ class ApplicationContext extends Context { @Override public Drawable getWallpaper() { - return getWallpaperManager().get(); + return getWallpaperManager().getDrawable(); } @Override public Drawable peekWallpaper() { - return getWallpaperManager().peek(); + return getWallpaperManager().peekDrawable(); } @Override @@ -534,12 +534,12 @@ class ApplicationContext extends Context { @Override public void setWallpaper(Bitmap bitmap) throws IOException { - getWallpaperManager().set(bitmap); + getWallpaperManager().setBitmap(bitmap); } @Override public void setWallpaper(InputStream data) throws IOException { - getWallpaperManager().set(data); + getWallpaperManager().setStream(data); } @Override diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index 1ed9b9f..7741668 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -18,6 +18,7 @@ package android.app; import android.os.ParcelFileDescriptor; import android.app.IWallpaperManagerCallback; +import android.content.ComponentName; /** @hide */ interface IWallpaperManager { @@ -28,6 +29,11 @@ interface IWallpaperManager { ParcelFileDescriptor setWallpaper(String name); /** + * Set the live wallpaper. + */ + void setWallpaperComponent(in ComponentName name); + + /** * Get the wallpaper. */ ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb); diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 405db83..9019b54 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2009 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 android.app; import android.content.Context; @@ -21,6 +37,14 @@ public class WallpaperManager { private static String TAG = "WallpaperManager"; private static boolean DEBUG = false; + /** + * Launch an activity for the user to pick the current global live + * wallpaper. + * @hide + */ + public static final String ACTION_LIVE_WALLPAPER_CHOOSER + = "android.service.wallpaper.LIVE_WALLPAPER_CHOOSER"; + private final Context mContext; static class Globals extends IWallpaperManagerCallback.Stub { @@ -88,13 +112,26 @@ public class WallpaperManager { } /** - * Like {@link #peek}, but always returns a valid Drawable. If + * Retrieve a WallpaperManager associated with the given Context. + */ + public static WallpaperManager getInstance(Context context) { + return (WallpaperManager)context.getSystemService( + Context.WALLPAPER_SERVICE); + } + + /** @hide */ + public IWallpaperManager getIWallpaperManager() { + return getGlobals().mService; + } + + /** + * Like {@link #peekDrawable}, 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 get() { - Drawable dr = peek(); + public Drawable getDrawable() { + Drawable dr = peekDrawable(); return dr != null ? dr : Resources.getSystem().getDrawable( com.android.internal.R.drawable.default_wallpaper); } @@ -108,7 +145,7 @@ public class WallpaperManager { * @return Returns a Drawable object that will draw the wallpaper or a * null pointer if these is none. */ - public Drawable peek() { + public Drawable peekDrawable() { return getGlobals().peekWallpaper(mContext); } @@ -123,7 +160,7 @@ public class WallpaperManager { * @throws IOException If an error occurs reverting to the default * wallpaper. */ - public void set(int resid) throws IOException { + public void setResource(int resid) throws IOException { try { Resources resources = mContext.getResources(); /* Set the wallpaper to the default values */ @@ -154,7 +191,7 @@ public class WallpaperManager { * @throws IOException If an error occurs reverting to the default * wallpaper. */ - public void set(Bitmap bitmap) throws IOException { + public void setBitmap(Bitmap bitmap) throws IOException { try { ParcelFileDescriptor fd = getGlobals().mService.setWallpaper(null); if (fd == null) { @@ -185,7 +222,7 @@ public class WallpaperManager { * @throws IOException If an error occurs reverting to the default * wallpaper. */ - public void set(InputStream data) throws IOException { + public void setStream(InputStream data) throws IOException { try { ParcelFileDescriptor fd = getGlobals().mService.setWallpaper(null); if (fd == null) { @@ -215,8 +252,8 @@ public class WallpaperManager { /** * Returns the desired minimum width for the wallpaper. Callers of - * {@link #set(android.graphics.Bitmap)} or - * {@link #set(java.io.InputStream)} should check this value + * {@link #setBitmap(android.graphics.Bitmap)} or + * {@link #setStream(java.io.InputStream)} should check this value * beforehand to make sure the supplied wallpaper respects the desired * minimum width. * @@ -238,8 +275,8 @@ public class WallpaperManager { /** * Returns the desired minimum height for the wallpaper. Callers of - * {@link #set(android.graphics.Bitmap)} or - * {@link #set(java.io.InputStream)} should check this value + * {@link #setBitmap(android.graphics.Bitmap)} or + * {@link #setStream(java.io.InputStream)} should check this value * beforehand to make sure the supplied wallpaper respects the desired * minimum height. * @@ -267,7 +304,7 @@ public class WallpaperManager { * @param minimumWidth Desired minimum width * @param minimumHeight Desired minimum height */ - public void setDimensionHints(int minimumWidth, int minimumHeight) { + public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) { try { getGlobals().mService.setDimensionHints(minimumWidth, minimumHeight); } catch (RemoteException e) { @@ -283,6 +320,6 @@ public class WallpaperManager { * wallpaper. */ public void clear() throws IOException { - set(com.android.internal.R.drawable.default_wallpaper); + setResource(com.android.internal.R.drawable.default_wallpaper); } } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 1105899..dbe6fb0 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -488,13 +488,13 @@ public abstract class Context { public abstract String[] databaseList(); /** - * @deprecated Use {@link android.app.WallpaperManager#get + * @deprecated Use {@link android.app.WallpaperManager#getDrawable * WallpaperManager.get()} instead. */ public abstract Drawable getWallpaper(); /** - * @deprecated Use {@link android.app.WallpaperManager#peek + * @deprecated Use {@link android.app.WallpaperManager#peekDrawable * WallpaperManager.peek()} instead. */ public abstract Drawable peekWallpaper(); @@ -512,13 +512,13 @@ public abstract class Context { public abstract int getWallpaperDesiredMinimumHeight(); /** - * @deprecated Use {@link android.app.WallpaperManager#set(Bitmap) + * @deprecated Use {@link android.app.WallpaperManager#setBitmap(Bitmap) * WallpaperManager.set()} instead. */ public abstract void setWallpaper(Bitmap bitmap) throws IOException; /** - * @deprecated Use {@link android.app.WallpaperManager#set(InputStream) + * @deprecated Use {@link android.app.WallpaperManager#setStream(InputStream) * WallpaperManager.set()} instead. */ public abstract void setWallpaper(InputStream data) throws IOException; diff --git a/core/java/android/service/wallpaper/IWallpaperConnection.aidl b/core/java/android/service/wallpaper/IWallpaperConnection.aidl new file mode 100644 index 0000000..b09ccab --- /dev/null +++ b/core/java/android/service/wallpaper/IWallpaperConnection.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 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 android.service.wallpaper; + +import android.os.ParcelFileDescriptor; +import android.service.wallpaper.IWallpaperEngine; + +/** + * @hide + */ +interface IWallpaperConnection { + void attachEngine(IWallpaperEngine engine); + ParcelFileDescriptor setWallpaper(String name); +} diff --git a/core/java/android/service/wallpaper/IWallpaperEngine.aidl b/core/java/android/service/wallpaper/IWallpaperEngine.aidl new file mode 100644 index 0000000..9586e34 --- /dev/null +++ b/core/java/android/service/wallpaper/IWallpaperEngine.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2009 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 android.service.wallpaper; + +/** + * @hide + */ +oneway interface IWallpaperEngine { + void destroy(); +} diff --git a/core/java/android/service/wallpaper/IWallpaperService.aidl b/core/java/android/service/wallpaper/IWallpaperService.aidl index 97e032b..eb58c3b 100644 --- a/core/java/android/service/wallpaper/IWallpaperService.aidl +++ b/core/java/android/service/wallpaper/IWallpaperService.aidl @@ -16,9 +16,12 @@ package android.service.wallpaper; +import android.service.wallpaper.IWallpaperConnection; + /** * @hide */ oneway interface IWallpaperService { - void onInterrupt(); + void attach(IWallpaperConnection connection, + IBinder windowToken, int reqWidth, int reqHeight); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index a729ed5..dbec1e6 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -17,17 +17,29 @@ package android.service.wallpaper; import com.android.internal.os.HandlerCaller; +import com.android.internal.view.BaseIWindow; +import com.android.internal.view.BaseSurfaceHolder; import android.app.Service; import android.content.Intent; +import android.graphics.Rect; +import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.util.Log; +import android.view.Gravity; +import android.view.IWindowSession; +import android.view.SurfaceHolder; +import android.view.View; +import android.view.ViewRoot; +import android.view.WindowManager; +import android.view.WindowManagerImpl; /** * A wallpaper service is responsible for showing a live wallpaper behind * applications that would like to sit on top of it. + * @hide Live Wallpaper */ public abstract class WallpaperService extends Service { /** @@ -36,48 +48,320 @@ public abstract class WallpaperService extends Service { public static final String SERVICE_INTERFACE = "android.service.wallpaper.WallpaperService"; - private static final String LOG_TAG = "WallpaperService"; - + static final String TAG = "WallpaperService"; + static final boolean DEBUG = true; + + private static final int DO_ATTACH = 10; + private static final int DO_DETACH = 20; + + private static final int MSG_UPDATE_SURFACE = 10000; + /** - * Implement to return the implementation of the internal accessibility - * service interface. Subclasses should not override. + * The actual implementation of a wallpaper. A wallpaper service may + * have multiple instances running (for example as a real wallpaper + * and as a preview), each of which is represented by its own Engine + * instance. */ - @Override - public final IBinder onBind(Intent intent) { - return new IWallpaperServiceWrapper(this); - } + public class Engine { + IWallpaperEngineWrapper mIWallpaperEngine; + + // Copies from mIWallpaperEngine. + HandlerCaller mCaller; + IWallpaperConnection mConnection; + IBinder mWindowToken; + + boolean mInitializing = true; + + // Current window state. + boolean mCreated; + boolean mIsCreating; + boolean mDrawingAllowed; + int mWidth; + int mHeight; + int mFormat; + int mType; + boolean mDestroyReportNeeded; + final Rect mVisibleInsets = new Rect(); + final Rect mWinFrame = new Rect(); + final Rect mContentInsets = new Rect(); + + final WindowManager.LayoutParams mLayout + = new WindowManager.LayoutParams(); + IWindowSession mSession; - /** - * Implements the internal {@link IWallpaperService} interface to convert - * incoming calls to it back to calls on an {@link WallpaperService}. - */ - class IWallpaperServiceWrapper extends IWallpaperService.Stub - implements HandlerCaller.Callback { + final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() { + + @Override + public boolean onAllowLockCanvas() { + return mDrawingAllowed; + } + + @Override + public void onRelayoutContainer() { + Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE); + mCaller.sendMessage(msg); + } + + @Override + public void onUpdateSurface() { + Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE); + mCaller.sendMessage(msg); + } - private static final int DO_ON_INTERRUPT = 10; + public boolean isCreating() { + return mIsCreating; + } + + public void setKeepScreenOn(boolean screenOn) { + // Ignore. + } + + }; - private final HandlerCaller mCaller; + final BaseIWindow mWindow = new BaseIWindow() { + + }; + + public void onAttach(SurfaceHolder surfaceHolder) { + } + + public void onDetach() { + } + + public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { + } - private WallpaperService mTarget; + public void onSurfaceCreated(SurfaceHolder holder) { + } - public IWallpaperServiceWrapper(WallpaperService context) { - mTarget = context; - mCaller = new HandlerCaller(context, this); + public void onSurfaceDestroyed(SurfaceHolder holder) { } - public void onInterrupt() { - Message message = mCaller.obtainMessage(DO_ON_INTERRUPT); - mCaller.sendMessage(message); + void updateSurface(boolean force) { + int myWidth = mSurfaceHolder.getRequestedWidth(); + if (myWidth <= 0) myWidth = mIWallpaperEngine.mReqWidth; + int myHeight = mSurfaceHolder.getRequestedHeight(); + if (myHeight <= 0) myHeight = mIWallpaperEngine.mReqHeight; + + final boolean creating = !mCreated; + final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat(); + final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight; + final boolean typeChanged = mType != mSurfaceHolder.getRequestedType(); + if (force || creating || formatChanged || sizeChanged || typeChanged) { + + if (DEBUG) Log.i(TAG, "Changes: creating=" + creating + + " format=" + formatChanged + " size=" + sizeChanged); + + try { + mWidth = myWidth; + mHeight = myHeight; + mFormat = mSurfaceHolder.getRequestedFormat(); + mType = mSurfaceHolder.getRequestedType(); + + // Scaling/Translate window's layout here because mLayout is not used elsewhere. + + // Places the window relative + mLayout.x = 0; + mLayout.y = 0; + mLayout.width = myWidth; + mLayout.height = myHeight; + + mLayout.format = mFormat; + mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + ; + + mLayout.memoryType = mType; + mLayout.token = mWindowToken; + + if (!mCreated) { + mLayout.type = WindowManager.LayoutParams.TYPE_WALLPAPER; + mLayout.gravity = Gravity.LEFT|Gravity.TOP; + mSession.add(mWindow, mLayout, View.VISIBLE, mContentInsets); + } + + mSurfaceHolder.mSurfaceLock.lock(); + mDrawingAllowed = true; + + final int relayoutResult = mSession.relayout( + mWindow, mLayout, mWidth, mHeight, + View.VISIBLE, false, mWinFrame, mContentInsets, + mVisibleInsets, mSurfaceHolder.mSurface); + + if (DEBUG) Log.i(TAG, "New surface: " + mSurfaceHolder.mSurface + + ", frame=" + mWinFrame); + + mSurfaceHolder.mSurfaceLock.unlock(); + + try { + mDestroyReportNeeded = true; + + SurfaceHolder.Callback callbacks[] = null; + synchronized (mSurfaceHolder.mCallbacks) { + final int N = mSurfaceHolder.mCallbacks.size(); + if (N > 0) { + callbacks = new SurfaceHolder.Callback[N]; + mSurfaceHolder.mCallbacks.toArray(callbacks); + } + } + + if (!mCreated) { + mIsCreating = true; + onSurfaceCreated(mSurfaceHolder); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceCreated(mSurfaceHolder); + } + } + } + if (creating || formatChanged || sizeChanged) { + onSurfaceChanged(mSurfaceHolder, mFormat, mWidth, mHeight); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceChanged(mSurfaceHolder, mFormat, mWidth, mHeight); + } + } + } + } finally { + mIsCreating = false; + mCreated = true; + if (creating || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) { + mSession.finishDrawing(mWindow); + } + } + } catch (RemoteException ex) { + } + if (DEBUG) Log.v( + TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y + + " w=" + mLayout.width + " h=" + mLayout.height); + } + } + + void attach(IWallpaperEngineWrapper wrapper) { + mIWallpaperEngine = wrapper; + mCaller = wrapper.mCaller; + mConnection = wrapper.mConnection; + mWindowToken = wrapper.mWindowToken; + mSurfaceHolder.setSizeFromLayout(); + mInitializing = true; + mSession = ViewRoot.getWindowSession(getMainLooper()); + mWindow.setSession(mSession); + + onAttach(mSurfaceHolder); + + mInitializing = false; + updateSurface(false); + } + + void detach() { + onDetach(); + if (mDestroyReportNeeded) { + mDestroyReportNeeded = false; + SurfaceHolder.Callback callbacks[]; + synchronized (mSurfaceHolder.mCallbacks) { + callbacks = new SurfaceHolder.Callback[ + mSurfaceHolder.mCallbacks.size()]; + mSurfaceHolder.mCallbacks.toArray(callbacks); + } + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceDestroyed(mSurfaceHolder); + } + } + if (mCreated) { + try { + mSession.remove(mWindow); + } catch (RemoteException e) { + } + mSurfaceHolder.mSurface.clear(); + mCreated = false; + } + } + } + + class IWallpaperEngineWrapper extends IWallpaperEngine.Stub + implements HandlerCaller.Callback { + private final HandlerCaller mCaller; + + final IWallpaperConnection mConnection; + final IBinder mWindowToken; + int mReqWidth; + int mReqHeight; + + Engine mEngine; + + IWallpaperEngineWrapper(WallpaperService context, + IWallpaperConnection conn, IBinder windowToken, + int reqWidth, int reqHeight) { + mCaller = new HandlerCaller(context, this); + mConnection = conn; + mWindowToken = windowToken; + mReqWidth = reqWidth; + mReqHeight = reqHeight; + + try { + conn.attachEngine(this); + } catch (RemoteException e) { + destroy(); + } + + Message msg = mCaller.obtainMessage(DO_ATTACH); + mCaller.sendMessage(msg); + } + + public void destroy() { + Message msg = mCaller.obtainMessage(DO_DETACH); + mCaller.sendMessage(msg); } public void executeMessage(Message message) { switch (message.what) { - case DO_ON_INTERRUPT : - //mTarget.onInterrupt(); + case DO_ATTACH: { + Engine engine = onCreateEngine(); + mEngine = engine; + engine.attach(this); return; + } + case DO_DETACH: { + mEngine.detach(); + return; + } + case MSG_UPDATE_SURFACE: + mEngine.updateSurface(false); + break; default : - Log.w(LOG_TAG, "Unknown message type " + message.what); + Log.w(TAG, "Unknown message type " + message.what); } } } + + /** + * Implements the internal {@link IWallpaperService} interface to convert + * incoming calls to it back to calls on an {@link WallpaperService}. + */ + class IWallpaperServiceWrapper extends IWallpaperService.Stub { + private final WallpaperService mTarget; + + public IWallpaperServiceWrapper(WallpaperService context) { + mTarget = context; + } + + public void attach(IWallpaperConnection conn, + IBinder windowToken, int reqWidth, int reqHeight) { + new IWallpaperEngineWrapper( + mTarget, conn, windowToken, reqWidth, reqHeight); + } + } + + /** + * Implement to return the implementation of the internal accessibility + * service interface. Subclasses should not override. + */ + @Override + public final IBinder onBind(Intent intent) { + return new IWallpaperServiceWrapper(this); + } + + public abstract Engine onCreateEngine(); } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 0d44b4e..216fc5e 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -192,22 +192,11 @@ public final class ViewRoot extends Handler implements ViewParent, private final int mDensity; - public ViewRoot(Context context) { - super(); - - if (MEASURE_LATENCY && lt == null) { - lt = new LatencyTimer(100, 1000); - } - - ++sInstanceCount; - - // Initialize the statics when this class is first instantiated. This is - // done here instead of in the static block because Zygote does not - // allow the spawning of threads. + public static IWindowSession getWindowSession(Looper mainLooper) { synchronized (mStaticInit) { if (!mInitialized) { try { - InputMethodManager imm = InputMethodManager.getInstance(context); + InputMethodManager imm = InputMethodManager.getInstance(mainLooper); sWindowSession = IWindowManager.Stub.asInterface( ServiceManager.getService("window")) .openSession(imm.getClient(), imm.getInputContext()); @@ -215,8 +204,24 @@ public final class ViewRoot extends Handler implements ViewParent, } catch (RemoteException e) { } } + return sWindowSession; + } + } + + public ViewRoot(Context context) { + super(); + + if (MEASURE_LATENCY && lt == null) { + lt = new LatencyTimer(100, 1000); } + ++sInstanceCount; + + // Initialize the statics when this class is first instantiated. This is + // done here instead of in the static block because Zygote does not + // allow the spawning of threads. + getWindowSession(context.getMainLooper()); + mThread = Thread.currentThread(); mLocation = new WindowLeaked(null); mLocation.fillInStackTrace(); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index c0be9e8..35d7cc9 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -314,6 +314,12 @@ public interface WindowManager extends ViewManager { public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12; /** + * Window type: wallpaper window, placed behind any window that wants + * to sit on top of the wallpaper. + */ + public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13; + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; @@ -479,16 +485,23 @@ public interface WindowManager extends ViewManager { * key guard or any other lock screens. Can be used with * {@link #FLAG_KEEP_SCREEN_ON} to turn screen on and display windows * directly before showing the key guard window - * - * {@hide} */ + */ public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000; + /** Window flag: ask that the system wallpaper be shown behind + * your window. The window surface must be translucent to be able + * to actually see the wallpaper behind it; this flag just ensures + * that the wallpaper surface will be there if this window actually + * has translucent regions. + */ + public static final int FLAG_SHOW_WALLPAPER = 0x00100000; + /** Window flag: special flag to limit the size of the window to be * original size ([320x480] x density). Used to create window for applications * running under compatibility mode. * * {@hide} */ - public static final int FLAG_COMPATIBLE_WINDOW = 0x00100000; + public static final int FLAG_COMPATIBLE_WINDOW = 0x20000000; /** Window flag: a special option intended for system dialogs. When * this flag is set, the window will demand focus unconditionally when diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index d797890..e30687f 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -446,13 +446,22 @@ public final class InputMethodManager { * @hide */ static public InputMethodManager getInstance(Context context) { + return getInstance(context.getMainLooper()); + } + + /** + * Internally, the input method manager can't be context-dependent, so + * we have this here for the places that need it. + * @hide + */ + static public InputMethodManager getInstance(Looper mainLooper) { synchronized (mInstanceSync) { if (mInstance != null) { return mInstance; } IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE); IInputMethodManager service = IInputMethodManager.Stub.asInterface(b); - mInstance = new InputMethodManager(service, context.getMainLooper()); + mInstance = new InputMethodManager(service, mainLooper); } return mInstance; } diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java index 932555d..2ab9e09 100644 --- a/core/java/com/android/internal/os/HandlerCaller.java +++ b/core/java/com/android/internal/os/HandlerCaller.java @@ -132,6 +132,14 @@ public class HandlerCaller { return mH.obtainMessage(what, arg1, arg2, arg3); } + public Message obtainMessageIIOO(int what, int arg1, int arg2, + Object arg3, Object arg4) { + SomeArgs args = obtainArgs(); + args.arg1 = arg3; + args.arg2 = arg4; + return mH.obtainMessage(what, arg1, arg2, args); + } + public Message obtainMessageIOO(int what, int arg1, Object arg2, Object arg3) { SomeArgs args = obtainArgs(); args.arg1 = arg2; diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java new file mode 100644 index 0000000..9c99e05 --- /dev/null +++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2009 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.internal.service.wallpaper; + +import android.app.WallpaperManager; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.service.wallpaper.WallpaperService; +import android.view.SurfaceHolder; + +/** + * Default built-in wallpaper that simply shows a static image. + */ +public class ImageWallpaper extends WallpaperService { + public WallpaperManager mWallpaperManager; + + class MyEngine extends Engine { + + Drawable mBackground; + + @Override + public void onAttach(SurfaceHolder surfaceHolder) { + super.onAttach(surfaceHolder); + mBackground = mWallpaperManager.getDrawable(); + } + + @Override + public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { + super.onSurfaceChanged(holder, format, width, height); + Canvas c = holder.lockCanvas(); + mBackground.setBounds(0, 0, width, height); + mBackground.draw(c); + Paint paint = new Paint(); + paint.setAntiAlias(true); + final float density = getResources().getDisplayMetrics().density; + paint.setTextSize(30 * density); + paint.setShadowLayer(5*density, 3*density, 3*density, 0xff000000); + paint.setARGB(255, 255, 255, 255); + c.drawText("Am I live?", 10, 60*density, paint); + holder.unlockCanvasAndPost(c); + } + + @Override + public void onSurfaceCreated(SurfaceHolder holder) { + super.onSurfaceCreated(holder); + } + + @Override + public void onSurfaceDestroyed(SurfaceHolder holder) { + super.onSurfaceDestroyed(holder); + } + + } + + @Override + public void onCreate() { + super.onCreate(); + mWallpaperManager = (WallpaperManager)getSystemService(WALLPAPER_SERVICE); + } + + public Engine onCreateEngine() { + return new MyEngine(); + } +} diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java new file mode 100644 index 0000000..7449067 --- /dev/null +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -0,0 +1,68 @@ +package com.android.internal.view; + +import android.graphics.Rect; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.view.IWindow; +import android.view.IWindowSession; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class BaseIWindow extends IWindow.Stub { + private IWindowSession mSession; + + public void setSession(IWindowSession session) { + mSession = session; + } + + public void resized(int w, int h, Rect coveredInsets, + Rect visibleInsets, boolean reportDraw) { + if (reportDraw) { + try { + mSession.finishDrawing(this); + } catch (RemoteException e) { + } + } + } + + public void dispatchKey(KeyEvent event) { + try { + mSession.finishKey(this); + } catch (RemoteException ex) { + } + } + + public void dispatchPointer(MotionEvent event, long eventTime) { + try { + if (event == null) { + event = mSession.getPendingPointerMove(this); + } else if (event.getAction() != MotionEvent.ACTION_OUTSIDE) { + mSession.finishKey(this); + } + } catch (RemoteException ex) { + } + } + + public void dispatchTrackball(MotionEvent event, long eventTime) { + try { + if (event == null) { + event = mSession.getPendingTrackballMove(this); + } else if (event.getAction() != MotionEvent.ACTION_OUTSIDE) { + mSession.finishKey(this); + } + } catch (RemoteException ex) { + } + } + + public void dispatchAppVisibility(boolean visible) { + } + + public void dispatchGetNewSurface() { + } + + public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) { + } + + public void executeCommand(String command, String parameters, ParcelFileDescriptor out) { + } +} diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java new file mode 100644 index 0000000..2364ae4 --- /dev/null +++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java @@ -0,0 +1,169 @@ +package com.android.internal.view; + +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.os.SystemClock; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; + +import java.util.ArrayList; +import java.util.concurrent.locks.ReentrantLock; + +public abstract class BaseSurfaceHolder implements SurfaceHolder { + private static final String TAG = "BaseSurfaceHolder"; + static final boolean DEBUG = false; + + public final ArrayList<SurfaceHolder.Callback> mCallbacks + = new ArrayList<SurfaceHolder.Callback>(); + + public final ReentrantLock mSurfaceLock = new ReentrantLock(); + public final Surface mSurface = new Surface(); + + int mRequestedWidth = -1; + int mRequestedHeight = -1; + int mRequestedFormat = PixelFormat.OPAQUE; + int mRequestedType = -1; + + long mLastLockTime = 0; + + int mType = -1; + final Rect mSurfaceFrame = new Rect(); + + public abstract void onUpdateSurface(); + public abstract void onRelayoutContainer(); + public abstract boolean onAllowLockCanvas(); + + public int getRequestedWidth() { + return mRequestedWidth; + } + + public int getRequestedHeight() { + return mRequestedHeight; + } + + public int getRequestedFormat() { + return mRequestedFormat; + } + + public int getRequestedType() { + return mRequestedType; + } + + public void addCallback(Callback callback) { + synchronized (mCallbacks) { + // This is a linear search, but in practice we'll + // have only a couple callbacks, so it doesn't matter. + if (mCallbacks.contains(callback) == false) { + mCallbacks.add(callback); + } + } + } + + public void removeCallback(Callback callback) { + synchronized (mCallbacks) { + mCallbacks.remove(callback); + } + } + + public void setFixedSize(int width, int height) { + if (mRequestedWidth != width || mRequestedHeight != height) { + mRequestedWidth = width; + mRequestedHeight = height; + onRelayoutContainer(); + } + } + + public void setSizeFromLayout() { + if (mRequestedWidth != -1 || mRequestedHeight != -1) { + mRequestedWidth = mRequestedHeight = -1; + onRelayoutContainer(); + } + } + + public void setFormat(int format) { + if (mRequestedFormat != format) { + mRequestedFormat = format; + onUpdateSurface(); + } + } + + public void setType(int type) { + switch (type) { + case SURFACE_TYPE_NORMAL: + case SURFACE_TYPE_HARDWARE: + case SURFACE_TYPE_GPU: + case SURFACE_TYPE_PUSH_BUFFERS: + if (mRequestedType != type) { + mRequestedType = type; + onUpdateSurface(); + } + break; + } + } + + public Canvas lockCanvas() { + return internalLockCanvas(null); + } + + public Canvas lockCanvas(Rect dirty) { + return internalLockCanvas(dirty); + } + + private final Canvas internalLockCanvas(Rect dirty) { + if (mType == SURFACE_TYPE_PUSH_BUFFERS) { + throw new BadSurfaceTypeException( + "Surface type is SURFACE_TYPE_PUSH_BUFFERS"); + } + mSurfaceLock.lock(); + + if (DEBUG) Log.i(TAG, "Locking canvas..,"); + + Canvas c = null; + if (onAllowLockCanvas()) { + Rect frame = dirty != null ? dirty : mSurfaceFrame; + try { + c = mSurface.lockCanvas(frame); + } catch (Exception e) { + Log.e(TAG, "Exception locking surface", e); + } + } + + if (DEBUG) Log.i(TAG, "Returned canvas: " + c); + if (c != null) { + mLastLockTime = SystemClock.uptimeMillis(); + return c; + } + + // If the Surface is not ready to be drawn, then return null, + // but throttle calls to this function so it isn't called more + // than every 100ms. + long now = SystemClock.uptimeMillis(); + long nextTime = mLastLockTime + 100; + if (nextTime > now) { + try { + Thread.sleep(nextTime-now); + } catch (InterruptedException e) { + } + now = SystemClock.uptimeMillis(); + } + mLastLockTime = now; + mSurfaceLock.unlock(); + + return null; + } + + public void unlockCanvasAndPost(Canvas canvas) { + mSurface.unlockCanvasAndPost(canvas); + mSurfaceLock.unlock(); + } + + public Surface getSurface() { + return mSurface; + } + + public Rect getSurfaceFrame() { + return mSurfaceFrame; + } +}; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 69ef96c..cf85af5 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -894,6 +894,13 @@ android:description="@string/permdesc_bindInputMethod" android:protectionLevel="signature" /> + <!-- Must be required by wallpaper services, to ensure that only the + system can bind to them. --> + <permission android:name="android.permission.BIND_WALLPAPER" + android:label="@string/permlab_bindWallpaper" + android:description="@string/permdesc_bindWallpaper" + android:protectionLevel="signature" /> + <!-- Allows low-level access to setting the orientation (actually rotation) of the screen. Not for use by normal applications. --> <permission android:name="android.permission.SET_ORIENTATION" @@ -1082,6 +1089,12 @@ android:permissionGroup="android.permission-group.SYSTEM_TOOLS" android:protectionLevel="signature" /> + <!-- Allows applications to set a live wallpaper. + @hide --> + <permission android:name="android.permission.SET_WALLPAPER_COMPONENT" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="signature" /> + <application android:process="system" android:persistent="true" android:hasCode="false" @@ -1140,7 +1153,14 @@ </activity> <service android:name="com.android.server.LoadAverageService" - android:exported="true" /> + android:exported="true" /> + + <service android:name="com.android.internal.service.wallpaper.ImageWallpaper" + android:permission="android.permission.BIND_WALLPAPER"> + <intent-filter> + <action android:name="android.service.wallpaper.WallpaperService" /> + </intent-filter> + </service> <receiver android:name="com.android.server.BootReceiver" > <intent-filter> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 558d91e..68f2070 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -599,6 +599,12 @@ interface of an input method. Should never be needed for normal applications.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_bindWallpaper">bind to a wallpaper</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_bindWallpaper">Allows the holder to bind to the top-level + interface of a wallpaper. Should never be needed for normal applications.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_setOrientation">change screen orientation</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_setOrientation">Allows an application to change |