diff options
author | Roman Birg <roman@cyngn.com> | 2014-04-24 22:22:45 -0700 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-10-26 02:32:21 -0700 |
commit | 565a22d702e689edfaaf108b96ec7d8d8f1109e5 (patch) | |
tree | 20d391813d53f39761f2095c36d051fc1ec17799 | |
parent | 46bb690eed5ac4ddb4fa0139098a5f92969573c1 (diff) | |
download | frameworks_base-565a22d702e689edfaaf108b96ec7d8d8f1109e5.zip frameworks_base-565a22d702e689edfaaf108b96ec7d8d8f1109e5.tar.gz frameworks_base-565a22d702e689edfaaf108b96ec7d8d8f1109e5.tar.bz2 |
frameworks: add keyguard wallpaper functionality to WallpaperManager
Adapted for cm-12.
Change-Id: I0eb1b5578b705c2ade4c0772fa86e09478b9f73e
Signed-off-by: Roman Birg <roman@cyngn.com>
20 files changed, 610 insertions, 24 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index f6e0735..a1cc8ec 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2096,7 +2096,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case KEYGUARD_GOING_AWAY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - keyguardGoingAway(data.readInt() != 0, data.readInt() != 0); + keyguardGoingAway(data.readInt() != 0, data.readInt() != 0, data.readInt() != 0); reply.writeNoException(); return true; } @@ -5263,12 +5263,14 @@ class ActivityManagerProxy implements IActivityManager } public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) throws RemoteException { + boolean keyguardGoingToNotificationShade, + boolean keyguardShowingMedia) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeInt(disableWindowAnimations ? 1 : 0); data.writeInt(keyguardGoingToNotificationShade ? 1 : 0); + data.writeInt(keyguardShowingMedia ? 1 : 0); mRemote.transact(KEYGUARD_GOING_AWAY_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index ef121ce..17d0fa1 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -411,7 +411,8 @@ public interface IActivityManager extends IInterface { public void keyguardWaitingForActivityDrawn() throws RemoteException; public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) throws RemoteException; + boolean keyguardGoingToNotificationShade, + boolean keyguardShowingMedia) throws RemoteException; public boolean shouldUpRecreateTask(IBinder token, String destAffinity) throws RemoteException; diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index ccba250..c717459 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -30,6 +30,12 @@ interface IWallpaperManager { * Set the wallpaper. */ ParcelFileDescriptor setWallpaper(String name, in String callingPackage); + + /** + * Set the keyguard wallpaper. + * @hide + */ + ParcelFileDescriptor setKeyguardWallpaper(String name, in String callingPackage); /** * Set the live wallpaper. @@ -46,6 +52,13 @@ interface IWallpaperManager { */ ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, out Bundle outParams); + + /** + * Get the keyguard wallpaper. + * @hide + */ + ParcelFileDescriptor getKeyguardWallpaper(IWallpaperManagerCallback cb, + out Bundle outParams); /** * Get information about a live wallpaper. @@ -57,6 +70,12 @@ interface IWallpaperManager { */ void clearWallpaper(in String callingPackage); + /* + * Clear the keyguard wallpaper. + * @hide + */ + void clearKeyguardWallpaper(); + /** * Return whether there is a wallpaper set with the given name. */ diff --git a/core/java/android/app/IWallpaperManagerCallback.aidl b/core/java/android/app/IWallpaperManagerCallback.aidl index 991b2bc..b217318 100644 --- a/core/java/android/app/IWallpaperManagerCallback.aidl +++ b/core/java/android/app/IWallpaperManagerCallback.aidl @@ -28,4 +28,9 @@ oneway interface IWallpaperManagerCallback { * Called when the wallpaper has changed */ void onWallpaperChanged(); + + /** + * Called when the keygaurd wallpaper has changed + */ + void onKeyguardWallpaperChanged(); } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 22e79b6..f545d84 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -33,6 +33,7 @@ import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; +import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; @@ -230,9 +231,10 @@ public class WallpaperManager { private IWallpaperManager mService; private Bitmap mWallpaper; private Bitmap mDefaultWallpaper; + private Bitmap mKeyguardWallpaper; private static final int MSG_CLEAR_WALLPAPER = 1; - + Globals(Looper looper) { IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE); mService = IWallpaperManager.Stub.asInterface(b); @@ -250,6 +252,12 @@ public class WallpaperManager { } } + public void onKeyguardWallpaperChanged() { + synchronized (this) { + mKeyguardWallpaper = null; + } + } + public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) { synchronized (this) { if (mService != null) { @@ -285,6 +293,23 @@ public class WallpaperManager { } } + /** + * @hide + */ + public Bitmap peekKeyguardWallpaperBitmap(Context context) { + synchronized (this) { + if (mKeyguardWallpaper != null) { + return mKeyguardWallpaper; + } + try { + mKeyguardWallpaper = getCurrentKeyguardWallpaperLocked(context); + } catch (OutOfMemoryError e) { + Log.w(TAG, "No memory load current keyguard wallpaper", e); + } + return mKeyguardWallpaper; + } + } + public void forgetLoadedWallpaper() { synchronized (this) { mWallpaper = null; @@ -321,7 +346,33 @@ public class WallpaperManager { } return null; } - + + private Bitmap getCurrentKeyguardWallpaperLocked(Context context) { + try { + Bundle params = new Bundle(); + ParcelFileDescriptor fd = mService.getKeyguardWallpaper(this, params); + if (fd != null) { + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + Bitmap bm = BitmapFactory.decodeFileDescriptor( + fd.getFileDescriptor(), null, options); + return bm; + } catch (OutOfMemoryError e) { + Log.w(TAG, "Can't decode file", e); + } finally { + try { + fd.close(); + } catch (IOException e) { + // Ignore + } + } + } + } catch (RemoteException e) { + // Ignore + } + return null; + } + private Bitmap getDefaultWallpaperLocked(Context context) { InputStream is = openDefaultWallpaper(context); if (is != null) { @@ -340,6 +391,18 @@ public class WallpaperManager { } return null; } + + /** @hide */ + public void clearKeyguardWallpaper() { + synchronized (this) { + try { + mService.clearKeyguardWallpaper(); + } catch (RemoteException e) { + // ignore + } + mKeyguardWallpaper = null; + } + } } private static final Object sSync = new Object[0]; @@ -599,6 +662,15 @@ public class WallpaperManager { return null; } + /** @hide */ + public Drawable getFastKeyguardDrawable() { + Bitmap bm = sGlobals.peekKeyguardWallpaperBitmap(mContext); + if (bm != null) { + return new FastBitmapDrawable(bm); + } + return null; + } + /** * Like {@link #getFastDrawable()}, but if there is no wallpaper set, * a null pointer is returned. @@ -624,6 +696,13 @@ public class WallpaperManager { } /** + * @hide + */ + public Bitmap getKeyguardBitmap() { + return sGlobals.peekKeyguardWallpaperBitmap(mContext); + } + + /** * Remove all internal references to the last loaded wallpaper. Useful * for apps that want to reduce memory usage when they only temporarily * need to have the wallpaper. After calling, the next request for the @@ -787,6 +866,36 @@ public class WallpaperManager { } /** + * @param bitmap + * @throws IOException + * @hide + */ + public void setKeyguardBitmap(Bitmap bitmap) throws IOException { + if (sGlobals.mService == null) { + Log.w(TAG, "WallpaperService not running"); + return; + } + try { + ParcelFileDescriptor fd = sGlobals.mService.setKeyguardWallpaper(null, + mContext.getOpPackageName()); + if (fd == null) { + return; + } + FileOutputStream fos = null; + try { + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos); + } finally { + if (fos != null) { + fos.close(); + } + } + } catch (RemoteException e) { + // Ignore + } + } + + /** * Change the current system wallpaper to a specific byte stream. The * give InputStream is copied into persistent storage and will now be * used as the wallpaper. Currently it must be either a JPEG or PNG @@ -826,6 +935,34 @@ public class WallpaperManager { } } + /** + * @hide + */ + public void setKeyguardStream(InputStream data) throws IOException { + if (sGlobals.mService == null) { + Log.w(TAG, "WallpaperService not running"); + return; + } + try { + ParcelFileDescriptor fd = sGlobals.mService.setKeyguardWallpaper(null, + mContext.getOpPackageName()); + if (fd == null) { + return; + } + FileOutputStream fos = null; + try { + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + setWallpaper(data, fos); + } finally { + if (fos != null) { + fos.close(); + } + } + } catch (RemoteException e) { + // Ignore + } + } + private void setWallpaper(InputStream data, FileOutputStream fos) throws IOException { byte[] buffer = new byte[32768]; @@ -1166,6 +1303,13 @@ public class WallpaperManager { } /** + * @hide + */ + public void clearKeyguardWallpaper() { + sGlobals.clearKeyguardWallpaper(); + } + + /** * Open stream representing the default static image wallpaper. * * @hide diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 92cf03e..9e742e5 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2084,6 +2084,15 @@ public class Intent implements Parcelable, Cloneable { */ @Deprecated @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED"; + + /** + * Broadcast Action: The current keyguard wallpaper configuration + * has changed and should be re-read. + * {@hide} + */ + public static final String ACTION_KEYGUARD_WALLPAPER_CHANGED = + "android.intent.action.KEYGUARD_WALLPAPER_CHANGED"; + /** * Broadcast Action: The current device {@link android.content.res.Configuration} * (orientation, locale, etc) has changed. When such a change happens, the diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 111f9a2..e98ef85 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -130,7 +130,7 @@ interface IWindowManager boolean inKeyguardRestrictedInputMode(); void dismissKeyguard(); void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade); + boolean keyguardGoingToNotificationShade, boolean keyguardShowingMedia); void closeSystemDialogs(String reason); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index cac2705..42cb816 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -778,7 +778,8 @@ public interface WindowManagerPolicy { * Create and return an animation to let the wallpaper disappear after being shown on a force * hiding window. */ - public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade); + public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade, + boolean keyguardShowingMedia); /** * Called from the input reader thread before a key is enqueued. diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 04b4033..8efbe7a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1490,6 +1490,14 @@ android:description="@string/permdesc_setWallpaperHints" android:protectionLevel="normal" /> + <!-- Allows applications to set the keyguard wallpaper + @hide --> + <permission android:name="android.permission.SET_KEYGUARD_WALLPAPER" + android:permissionGroup="android.permission-group.WALLPAPER" + android:protectionLevel="normal" + android:label="@string/permlab_setKeyguardWallpaper" + android:description="@string/permdesc_setKeyguardWallpaper" /> + <!-- ============================================ --> <!-- Permissions for changing the system clock --> <!-- ============================================ --> diff --git a/core/res/res/anim/lock_screen_wallpaper_exit_noop.xml b/core/res/res/anim/lock_screen_wallpaper_exit_noop.xml new file mode 100644 index 0000000..4cc5c70 --- /dev/null +++ b/core/res/res/anim/lock_screen_wallpaper_exit_noop.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 The CyanogenMod 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. +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:shareInterpolator="false" android:startOffset="100"> + <alpha + android:fromAlpha="0.0" android:toAlpha="0.0" + android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" + android:interpolator="@interpolator/fast_out_linear_in" + android:duration="150"/> + + <!-- Empty animation so the animation has same duration as lock_screen_behind_enter animation + --> + <translate android:fromYDelta="0" android:toYDelta="0" + android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" + android:interpolator="@interpolator/linear" + android:duration="300" /> +</set>
\ No newline at end of file diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml index 3cf2992..f766150 100644 --- a/core/res/res/values/cm_strings.xml +++ b/core/res/res/values/cm_strings.xml @@ -56,6 +56,10 @@ <!-- label for item that opens the profile choosing dialog --> <string name="global_action_choose_profile">Profile</string> + <!-- Title of an application permission, listed so the user can choose whether they want the application to do this. --> + <string name="permlab_setKeyguardWallpaper">set keyguard 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_setKeyguardWallpaper">Allows an app to change the lock screen wallpaper.</string> <!-- label for item that reboots the phone in phone options dialog --> <string name="global_action_reboot">Reboot</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f23c69c..12619ff 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1894,6 +1894,7 @@ <java-symbol type="anim" name="lock_screen_behind_enter_fade_in" /> <java-symbol type="anim" name="lock_screen_wallpaper_exit" /> <java-symbol type="anim" name="launch_task_behind_source" /> + <java-symbol type="anim" name="lock_screen_wallpaper_exit_noop" /> <java-symbol type="bool" name="config_alwaysUseCdmaRssi" /> <java-symbol type="dimen" name="status_bar_icon_size" /> diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index af24b4a..008c833 100755 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1441,7 +1441,8 @@ public class KeyguardViewMediator extends SystemUI { ActivityManagerNative.getDefault().keyguardGoingAway( mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock() || mWakeAndUnlocking, - mStatusBarKeyguardViewManager.isGoingToNotificationShade()); + mStatusBarKeyguardViewManager.isGoingToNotificationShade(), + mStatusBarKeyguardViewManager.isKeyguardShowingMedia()); } catch (RemoteException e) { Log.e(TAG, "Error while calling WindowManager", e); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 3d8ab83..99244da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -27,6 +27,7 @@ import android.app.IActivityManager; import android.app.Notification; import android.app.PendingIntent; import android.app.StatusBarManager; +import android.app.WallpaperManager; import android.content.BroadcastReceiver; import android.content.ComponentCallbacks2; import android.content.ContentResolver; @@ -314,6 +315,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, KeyguardIndicationController mKeyguardIndicationController; private boolean mKeyguardFadingAway; + private boolean mKeyguardShowingMedia; private long mKeyguardFadingAwayDelay; private long mKeyguardFadingAwayDuration; @@ -959,6 +961,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED); context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); IntentFilter demoFilter = new IntentFilter(); @@ -1732,18 +1735,30 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, + " state=" + mState); } - Bitmap artworkBitmap = null; + Bitmap backdropBitmap = null; + + // apply any album artwork first if (mMediaMetadata != null) { - artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART); - if (artworkBitmap == null) { - artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART); + backdropBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART); + if (backdropBitmap == null) { + backdropBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART); // might still be null } } - final boolean hasArtwork = artworkBitmap != null; + // apply user lockscreen image + if (backdropBitmap == null) { + WallpaperManager wm = (WallpaperManager) + mContext.getSystemService(Context.WALLPAPER_SERVICE); + if (wm != null) { + backdropBitmap = wm.getKeyguardBitmap(); + } + } + + final boolean hasBackdrop = backdropBitmap != null; + mKeyguardShowingMedia = hasBackdrop; - if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) + if ((hasBackdrop || DEBUG_MEDIA_FAKE_ARTWORK) && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { // time to show some art! if (mBackdrop.getVisibility() != View.VISIBLE) { @@ -1774,7 +1789,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mBackdropBack.setBackgroundColor(0xFFFFFFFF); mBackdropBack.setImageDrawable(new ColorDrawable(c)); } else { - mBackdropBack.setImageBitmap(artworkBitmap); + mBackdropBack.setImageBitmap(backdropBitmap); } if (mScrimSrcModeEnabled) { mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode); @@ -1969,6 +1984,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return mLeaveOpenOnKeyguardHide; } + public boolean isKeyguardShowingMedia() { + return mKeyguardShowingMedia; + } + public boolean isQsExpanded() { return mNotificationPanel.isQsExpanded(); } @@ -2975,6 +2994,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (DEBUG_MEDIA_FAKE_ARTWORK) { updateMediaMetaData(true); } + } else if (Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED.equals(action)) { + updateMediaMetaData(true); } } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 7dd3e7c..a83fd8f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -495,4 +495,8 @@ public class StatusBarKeyguardViewManager { mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true); } } + + public boolean isKeyguardShowingMedia() { + return mPhoneStatusBar.isKeyguardShowingMedia(); + } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index af803ff..7bf09b1 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6315,14 +6315,16 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) { + boolean keyguardGoingToNotificationShade, + boolean keyguardShowingMedia) { enforceNotIsolatedCaller("keyguardGoingAway"); final long token = Binder.clearCallingIdentity(); try { synchronized (this) { if (DEBUG_LOCKSCREEN) logLockScreen(""); mWindowManager.keyguardGoingAway(disableWindowAnimations, - keyguardGoingToNotificationShade); + keyguardGoingToNotificationShade, + keyguardShowingMedia); if (mLockScreenShown == LOCK_SCREEN_SHOWN) { mLockScreenShown = LOCK_SCREEN_HIDDEN; updateSleepIfNeededLocked(); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 3d32d17..b1a4484 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -2942,9 +2942,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override - public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) { + public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade, + boolean keyguardShowingMedia) { if (goingToNotificationShade) { return null; + } else if (keyguardShowingMedia) { + return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit_noop); } else { return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit); } diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 7784884..420e775 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -106,6 +106,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128; static final String WALLPAPER = "wallpaper"; static final String WALLPAPER_INFO = "wallpaper_info.xml"; + static final String KEYGUARD_WALLPAPER = "keyguard_wallpaper"; + static final String KEYGUARD_WALLPAPER_INFO = "keyguard_wallpaper_info.xml"; /** * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks @@ -116,17 +118,21 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { private class WallpaperObserver extends FileObserver { final WallpaperData mWallpaper; + final KeyguardWallpaperData mKeyguardWallpaper; final File mWallpaperDir; final File mWallpaperFile; final File mWallpaperInfoFile; + final File mKeyguardWallpaperFile; - public WallpaperObserver(WallpaperData wallpaper) { + public WallpaperObserver(WallpaperData wallpaper, KeyguardWallpaperData keyguardWallpaper) { super(getWallpaperDir(wallpaper.userId).getAbsolutePath(), CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF); mWallpaperDir = getWallpaperDir(wallpaper.userId); mWallpaper = wallpaper; mWallpaperFile = new File(mWallpaperDir, WALLPAPER); mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO); + mKeyguardWallpaper = keyguardWallpaper; + mKeyguardWallpaperFile = new File(mWallpaperDir, KEYGUARD_WALLPAPER); } @Override @@ -145,6 +151,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { Binder.restoreCallingIdentity(origId); } if (mWallpaperFile.equals(changedFile)) { + // changing the wallpaper means we'll need to back up the new one + long origId = Binder.clearCallingIdentity(); + BackupManager bm = new BackupManager(mContext); + bm.dataChanged(); + Binder.restoreCallingIdentity(origId); + notifyCallbacksLocked(mWallpaper); final boolean written = (event == CLOSE_WRITE || event == MOVED_TO); if (mWallpaper.wallpaperComponent == null @@ -157,6 +169,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { false, mWallpaper, null); saveSettingsLocked(mWallpaper); } + } else if (mKeyguardWallpaperFile.equals(changedFile)) { + notifyCallbacksLocked(mKeyguardWallpaper); + if (event == CLOSE_WRITE + || mKeyguardWallpaper.imageWallpaperPending) { + mKeyguardWallpaper.imageWallpaperPending = false; + saveSettingsLocked(mKeyguardWallpaper); + } } } } @@ -176,6 +195,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { final ComponentName mImageWallpaper; SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>(); + SparseArray<KeyguardWallpaperData> mKeyguardWallpaperMap + = new SparseArray<KeyguardWallpaperData>(); int mCurrentUserId; @@ -227,6 +248,37 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + static class KeyguardWallpaperData { + + int userId; + + File wallpaperFile; + + /** + * Client is currently writing a new image wallpaper. + */ + boolean imageWallpaperPending; + + /** + * Resource name if using a picture from the wallpaper gallery + */ + String name = ""; + + /** + * List of callbacks registered they should each be notified when the wallpaper is changed. + */ + private RemoteCallbackList<IWallpaperManagerCallback> callbacks + = new RemoteCallbackList<IWallpaperManagerCallback>(); + + int width = -1; + int height = -1; + + KeyguardWallpaperData(int userId) { + this.userId = userId; + wallpaperFile = new File(getWallpaperDir(userId), KEYGUARD_WALLPAPER); + } + } + class WallpaperConnection extends IWallpaperConnection.Stub implements ServiceConnection { final WallpaperInfo mInfo; @@ -486,6 +538,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { mMonitor.register(context, null, UserHandle.ALL, true); getWallpaperDir(UserHandle.USER_OWNER).mkdirs(); loadSettingsLocked(UserHandle.USER_OWNER); + loadKeyguardSettingsLocked(UserHandle.USER_OWNER); } private static File getWallpaperDir(int userId) { @@ -504,8 +557,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { public void systemRunning() { if (DEBUG) Slog.v(TAG, "systemReady"); WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER); + KeyguardWallpaperData keyguardWallpaper = mKeyguardWallpaperMap.get(UserHandle.USER_OWNER); switchWallpaper(wallpaper, null); - wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper); + wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper, keyguardWallpaper); wallpaper.wallpaperObserver.startWatching(); IntentFilter userFilter = new IntentFilter(); @@ -572,6 +626,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { wallpaper.wallpaperObserver = null; } mWallpaperMap.remove(userId); + mKeyguardWallpaperMap.remove(userId); } } } @@ -584,6 +639,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { wallpaperFile.delete(); File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO); wallpaperInfoFile.delete(); + File keyguardWallpaperFile = new File(getWallpaperDir(userId), KEYGUARD_WALLPAPER); + keyguardWallpaperFile.delete(); + File keyguardWallpaperInfoFile = new File(getWallpaperDir(userId), + KEYGUARD_WALLPAPER_INFO); + keyguardWallpaperInfoFile.delete(); } } @@ -591,9 +651,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { synchronized (mLock) { mCurrentUserId = userId; WallpaperData wallpaper = getWallpaperSafeLocked(userId); + KeyguardWallpaperData keyguardWallpaper = getKeyguardWallpaperSafeLocked(userId); // Not started watching yet, in case wallpaper data was loaded for other reasons. if (wallpaper.wallpaperObserver == null) { - wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper); + wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper, keyguardWallpaper); wallpaper.wallpaperObserver.startWatching(); } switchWallpaper(wallpaper, reply); @@ -669,6 +730,40 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + /** + * @hide + */ + public void clearKeyguardWallpaper() { + if (DEBUG) Slog.v(TAG, "clearWallpaper"); + synchronized (mLock) { + clearKeyguardWallpaperLocked(UserHandle.getCallingUserId(), null); + } + } + + void clearKeyguardWallpaperLocked(int userId, IRemoteCallback reply) { + KeyguardWallpaperData wallpaper = mKeyguardWallpaperMap.get(userId); + final long ident = Binder.clearCallingIdentity(); + wallpaper.imageWallpaperPending = false; + wallpaper.height = -1; + wallpaper.width = -1; + wallpaper.name = ""; + + File f = new File(getWallpaperDir(userId), KEYGUARD_WALLPAPER); + if (f.exists()) { + f.delete(); + } + if (userId != mCurrentUserId) + return; + Binder.restoreCallingIdentity(ident); + + if (reply != null) { + try { + reply.sendResult(null); + } catch (RemoteException e1) { + } + } + } + public boolean hasNamedWallpaper(String name) { synchronized (mLock) { List<UserInfo> users; @@ -837,6 +932,39 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + /** @hide */ + public ParcelFileDescriptor getKeyguardWallpaper(IWallpaperManagerCallback cb, + Bundle outParams) { + synchronized (mLock) { + // This returns the current user's wallpaper, if called by a system service. Else it + // returns the wallpaper for the calling user. + int callingUid = Binder.getCallingUid(); + int wallpaperUserId = 0; + if (callingUid == android.os.Process.SYSTEM_UID) { + wallpaperUserId = mCurrentUserId; + } else { + wallpaperUserId = UserHandle.getUserId(callingUid); + } + KeyguardWallpaperData wallpaper = mKeyguardWallpaperMap.get(wallpaperUserId); + try { + if (outParams != null) { + outParams.putInt("width", wallpaper.width); + outParams.putInt("height", wallpaper.height); + } + wallpaper.callbacks.register(cb); + File f = new File(getWallpaperDir(wallpaperUserId), KEYGUARD_WALLPAPER); + if (!f.exists()) { + return null; + } + return ParcelFileDescriptor.open(f, MODE_READ_ONLY); + } catch (FileNotFoundException e) { + /* Shouldn't happen as we check to see if the file exists */ + Slog.w(TAG, "Error getting wallpaper", e); + } + return null; + } + } + public WallpaperInfo getWallpaperInfo() { int userId = UserHandle.getCallingUserId(); synchronized (mLock) { @@ -848,6 +976,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + /** @hide */ + public boolean isKeyguardWallpaperSet() { + int userId = UserHandle.getCallingUserId(); + synchronized (mLock) { + KeyguardWallpaperData data = mKeyguardWallpaperMap.get(userId); + return data.wallpaperFile.exists(); + } + } + public ParcelFileDescriptor setWallpaper(String name, String callingPackage) { checkPermission(android.Manifest.permission.SET_WALLPAPER); if (!isWallpaperSupported(callingPackage)) { @@ -901,6 +1038,58 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + public ParcelFileDescriptor setKeyguardWallpaper(String name, String callingPackage) { + checkPermission(android.Manifest.permission.SET_KEYGUARD_WALLPAPER); + if (!isWallpaperSupported(callingPackage)) { + return null; + } + synchronized (mLock) { + if (DEBUG) Slog.v(TAG, "setKeyguardWallpaper"); + int userId = UserHandle.getCallingUserId(); + KeyguardWallpaperData wallpaper = mKeyguardWallpaperMap.get(userId); + if (wallpaper == null) { + throw new IllegalStateException("Keyguard wallpaper not yet initialized for user " + + userId); + } + final long ident = Binder.clearCallingIdentity(); + try { + ParcelFileDescriptor pfd = updateKeyguardWallpaperBitmapLocked(name, wallpaper); + if (pfd != null) { + wallpaper.imageWallpaperPending = true; + } + return pfd; + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + public ParcelFileDescriptor updateKeyguardWallpaperBitmapLocked(String name, + KeyguardWallpaperData wallpaper) { + if (name == null) name = ""; + try { + File dir = getWallpaperDir(wallpaper.userId); + if (!dir.exists()) { + dir.mkdir(); + FileUtils.setPermissions( + dir.getPath(), + FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, + -1, -1); + } + File file = new File(dir, KEYGUARD_WALLPAPER); + ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, + MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE); + if (!SELinux.restorecon(file)) { + return null; + } + wallpaper.name = name; + return fd; + } catch (FileNotFoundException e) { + Slog.w(TAG, "Error setting wallpaper", e); + } + return null; + } + // ToDo: Remove this version of the function public void setWallpaperComponent(ComponentName name) { checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT); @@ -1125,6 +1314,22 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId)); } + private void notifyCallbacksLocked(KeyguardWallpaperData wallpaper) { + final int n = wallpaper.callbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + wallpaper.callbacks.getBroadcastItem(i).onKeyguardWallpaperChanged(); + } catch (RemoteException e) { + + // The RemoteCallbackList will take care of removing + // the dead object for us. + } + } + wallpaper.callbacks.finishBroadcast(); + final Intent intent = new Intent(Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED); + mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId)); + } + private void checkPermission(String permission) { if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) { throw new SecurityException("Access denied to process: " + Binder.getCallingPid() @@ -1142,7 +1347,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } private static JournaledFile makeJournaledFile(int userId) { - final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath(); + return makeJournaledFile(WALLPAPER_INFO, userId); + } + + private static JournaledFile makeJournaledFile(String name, int userId) { + final String base = new File(getWallpaperDir(userId), name).getAbsolutePath(); return new JournaledFile(new File(base), new File(base + ".tmp")); } @@ -1195,6 +1404,36 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + private void saveSettingsLocked(KeyguardWallpaperData wallpaper) { + JournaledFile journal = makeJournaledFile(KEYGUARD_WALLPAPER_INFO, wallpaper.userId); + FileOutputStream stream = null; + try { + stream = new FileOutputStream(journal.chooseForWrite(), false); + XmlSerializer out = new FastXmlSerializer(); + out.setOutput(stream, "utf-8"); + out.startDocument(null, true); + + out.startTag(null, "kwp"); + out.attribute(null, "width", Integer.toString(wallpaper.width)); + out.attribute(null, "height", Integer.toString(wallpaper.height)); + out.attribute(null, "name", wallpaper.name); + out.endTag(null, "kwp"); + + out.endDocument(); + stream.close(); + journal.commit(); + } catch (IOException e) { + try { + if (stream != null) { + stream.close(); + } + } catch (IOException ex) { + // Ignore + } + journal.rollback(); + } + } + private void migrateFromOld() { File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY); File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY); @@ -1232,6 +1471,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { return wallpaper; } + private KeyguardWallpaperData getKeyguardWallpaperSafeLocked(int userId) { + KeyguardWallpaperData wallpaper = mKeyguardWallpaperMap.get(userId); + if (wallpaper == null) { + loadKeyguardSettingsLocked(userId); + wallpaper = mKeyguardWallpaperMap.get(userId); + } + return wallpaper; + } + + private void loadSettingsLocked(int userId) { if (DEBUG) Slog.v(TAG, "loadSettingsLocked"); @@ -1326,6 +1575,84 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + private void loadKeyguardSettingsLocked(int userId) { + if (DEBUG) Slog.v(TAG, "loadKeyguardSettingsLocked"); + + JournaledFile journal = makeJournaledFile(KEYGUARD_WALLPAPER_INFO, userId); + FileInputStream stream = null; + File file = journal.chooseForRead(); + if (!file.exists()) { + // This should only happen one time, when upgrading from a legacy system + migrateFromOld(); + } + KeyguardWallpaperData keyguardWallpaper = mKeyguardWallpaperMap.get(userId); + if (keyguardWallpaper == null) { + keyguardWallpaper = new KeyguardWallpaperData(userId); + mKeyguardWallpaperMap.put(userId, keyguardWallpaper); + } + boolean success = false; + try { + stream = new FileInputStream(file); + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(stream, null); + + int type; + do { + type = parser.next(); + if (type == XmlPullParser.START_TAG) { + String tag = parser.getName(); + if ("kwp".equals(tag)) { + keyguardWallpaper.width = Integer.parseInt(parser.getAttributeValue(null, + "width")); + keyguardWallpaper.height = Integer.parseInt(parser + .getAttributeValue(null, "height")); + keyguardWallpaper.name = parser.getAttributeValue(null, "name"); + if (DEBUG) { + Slog.v(TAG, "mWidth:" + keyguardWallpaper.width); + Slog.v(TAG, "mHeight:" + keyguardWallpaper.height); + Slog.v(TAG, "mName:" + keyguardWallpaper.name); + } + } + } + } while (type != XmlPullParser.END_DOCUMENT); + success = true; + } catch (FileNotFoundException e) { + Slog.w(TAG, "no current wallpaper -- first boot?"); + } catch (NullPointerException e) { + Slog.w(TAG, "failed parsing " + file + " " + e); + } catch (NumberFormatException e) { + Slog.w(TAG, "failed parsing " + file + " " + e); + } catch (XmlPullParserException e) { + Slog.w(TAG, "failed parsing " + file + " " + e); + } catch (IOException e) { + Slog.w(TAG, "failed parsing " + file + " " + e); + } catch (IndexOutOfBoundsException e) { + Slog.w(TAG, "failed parsing " + file + " " + e); + } + try { + if (stream != null) { + stream.close(); + } + } catch (IOException e) { + // Ignore + } + + if (!success) { + keyguardWallpaper.width = -1; + keyguardWallpaper.height = -1; + keyguardWallpaper.name = ""; + } + + // We always want to have some reasonable width hint. + int baseSize = getMaximumSizeDimension(); + if (keyguardWallpaper.width < baseSize) { + keyguardWallpaper.width = baseSize; + } + if (keyguardWallpaper.height < baseSize) { + keyguardWallpaper.height = baseSize; + } + } + private int getMaximumSizeDimension() { WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); Display d = wm.getDefaultDisplay(); diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 85a9624..c5cd729 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -92,6 +92,7 @@ public class WindowAnimator { boolean mKeyguardGoingAway; boolean mKeyguardGoingAwayToNotificationShade; boolean mKeyguardGoingAwayDisableWindowAnimations; + boolean mKeyguardGoingAwayShowingMedia; /** Use one animation for all entering activities after keyguard is dismissed. */ Animation mPostKeyguardExitAnimation; @@ -486,7 +487,7 @@ public class WindowAnimator { && !mKeyguardGoingAwayDisableWindowAnimations) { if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away"); Animation a = mPolicy.createForceHideWallpaperExitAnimation( - mKeyguardGoingAwayToNotificationShade); + mKeyguardGoingAwayToNotificationShade, mKeyguardGoingAwayShowingMedia); if (a != null) { wallpaper.mWinAnimator.setAnimation(a); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 909639f..ca08471 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5466,7 +5466,7 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) { + boolean keyguardGoingToNotificationShade, boolean keyguardShowingMedia) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires DISABLE_KEYGUARD permission"); @@ -5477,6 +5477,7 @@ public class WindowManagerService extends IWindowManager.Stub mAnimator.mKeyguardGoingAway = true; mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade; mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations; + mAnimator.mKeyguardGoingAwayShowingMedia = keyguardShowingMedia; requestTraversalLocked(); } } |