1e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos/* 2e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * Copyright (C) 2016 The Android Open Source Project 3e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * 4e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * Licensed under the Apache License, Version 2.0 (the "License"); 5e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * you may not use this file except in compliance with the License. 6e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * You may obtain a copy of the License at 7e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * 8e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * http://www.apache.org/licenses/LICENSE-2.0 9e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * 10e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * Unless required by applicable law or agreed to in writing, software 11e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * distributed under the License is distributed on an "AS IS" BASIS, 12e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * See the License for the specific language governing permissions and 14e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * limitations under the License 15e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos */ 16e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 17e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roospackage com.android.systemui.statusbar.phone; 18e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 19751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roosimport android.annotation.Nullable; 20e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.app.ActivityManager; 21e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.app.IWallpaperManager; 22e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.app.IWallpaperManagerCallback; 23e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.app.WallpaperManager; 24e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.content.Context; 253b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roosimport android.content.res.Resources; 26e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.graphics.Bitmap; 27e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.graphics.BitmapFactory; 283b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roosimport android.graphics.Rect; 29d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roosimport android.graphics.Xfermode; 303b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roosimport android.graphics.drawable.BitmapDrawable; 31751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roosimport android.graphics.drawable.Drawable; 323b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roosimport android.graphics.drawable.DrawableWrapper; 337e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roosimport android.os.AsyncTask; 34e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.os.Handler; 35e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.os.ParcelFileDescriptor; 36e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.os.RemoteException; 37e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.os.ServiceManager; 3812a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshevimport android.os.UserHandle; 39e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.util.Log; 40e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 41d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggiimport com.android.keyguard.KeyguardUpdateMonitor; 42d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi 43e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport libcore.io.IoUtils; 44e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 4512a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshevimport java.util.Objects; 4612a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev 47e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos/** 48e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * Manages the lockscreen wallpaper. 49e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos */ 50e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roospublic class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implements Runnable { 51e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 52e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos private static final String TAG = "LockscreenWallpaper"; 53e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 542a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk private final StatusBar mBar; 5512a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev private final WallpaperManager mWallpaperManager; 56e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos private final Handler mH; 57d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi private final KeyguardUpdateMonitor mUpdateMonitor; 58e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 59e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos private boolean mCached; 60e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos private Bitmap mCache; 6112a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev private int mCurrentUserId; 6212a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev // The user selected in the UI, or null if no user is selected or UI doesn't support selecting 6312a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev // users. 6412a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev private UserHandle mSelectedUser; 657e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos private AsyncTask<Void, Void, LoaderResult> mLoader; 66e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 672a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk public LockscreenWallpaper(Context ctx, StatusBar bar, Handler h) { 68e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos mBar = bar; 69e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos mH = h; 7012a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE); 7112a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev mCurrentUserId = ActivityManager.getCurrentUser(); 72d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi mUpdateMonitor = KeyguardUpdateMonitor.getInstance(ctx); 73e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 747e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos IWallpaperManager service = IWallpaperManager.Stub.asInterface( 757e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos ServiceManager.getService(Context.WALLPAPER_SERVICE)); 76e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos try { 777e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos service.setLockWallpaperCallback(this); 78e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } catch (RemoteException e) { 79e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos Log.e(TAG, "System dead?" + e); 80e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 81e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 82e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 83e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos public Bitmap getBitmap() { 847e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (mCached) { 857e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return mCache; 867e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 877e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (!mWallpaperManager.isWallpaperSupported()) { 887e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCached = true; 897e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCache = null; 907e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return null; 917e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 927e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 937e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos LoaderResult result = loadBitmap(mCurrentUserId, mSelectedUser); 947e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (result.success) { 957e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCached = true; 96d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi mUpdateMonitor.setHasLockscreenWallpaper(result.bitmap != null); 977e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCache = result.bitmap; 987e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 997e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return mCache; 1007e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1017e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1027e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos public LoaderResult loadBitmap(int currentUserId, UserHandle selectedUser) { 1037e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos // May be called on any thread - only use thread safe operations. 1047e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1057e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK 1067e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos // wallpaper. 1077e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos final int lockWallpaperUserId = 1087e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos selectedUser != null ? selectedUser.getIdentifier() : currentUserId; 1097e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos ParcelFileDescriptor fd = mWallpaperManager.getWallpaperFile( 1107e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos WallpaperManager.FLAG_LOCK, lockWallpaperUserId); 1117e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1127e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (fd != null) { 1137e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos try { 1147e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos BitmapFactory.Options options = new BitmapFactory.Options(); 1157e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return LoaderResult.success(BitmapFactory.decodeFileDescriptor( 1167e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos fd.getFileDescriptor(), null, options)); 1177e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } catch (OutOfMemoryError e) { 1187e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos Log.w(TAG, "Can't decode file", e); 1197e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return LoaderResult.fail(); 1207e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } finally { 1217e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos IoUtils.closeQuietly(fd); 122e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 1237e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } else { 1244324f9f2476afc08e41700faa23ee33881d0d3b8Evan Rosky if (selectedUser != null) { 1254324f9f2476afc08e41700faa23ee33881d0d3b8Evan Rosky // Show the selected user's static wallpaper. 1267e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return LoaderResult.success( 1277e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mWallpaperManager.getBitmapAsUser(selectedUser.getIdentifier())); 1287e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 129e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } else { 1304324f9f2476afc08e41700faa23ee33881d0d3b8Evan Rosky // When there is no selected user, show the system wallpaper 1317e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return LoaderResult.success(null); 132e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 133e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 134e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 135e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 13612a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev public void setCurrentUser(int user) { 13712a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev if (user != mCurrentUserId) { 13813a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky if (mSelectedUser == null || user != mSelectedUser.getIdentifier()) { 13913a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky mCached = false; 14013a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky } 14112a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev mCurrentUserId = user; 142e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 143e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 144e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 14512a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev public void setSelectedUser(UserHandle selectedUser) { 14612a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev if (Objects.equals(selectedUser, mSelectedUser)) { 14712a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev return; 14812a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev } 14912a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev mSelectedUser = selectedUser; 1507e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos postUpdateWallpaper(); 15112a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev } 15212a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev 153e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos @Override 154e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos public void onWallpaperChanged() { 155e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos // Called on Binder thread. 1567e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos postUpdateWallpaper(); 1577e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1587e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1597e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos private void postUpdateWallpaper() { 160e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos mH.removeCallbacks(this); 161e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos mH.post(this); 162e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 163e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 164e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos @Override 165e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos public void run() { 166e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos // Called in response to onWallpaperChanged on the main thread. 1677e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1687e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (mLoader != null) { 1697e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mLoader.cancel(false /* interrupt */); 1707e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1717e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1727e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos final int currentUser = mCurrentUserId; 1737e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos final UserHandle selectedUser = mSelectedUser; 1747e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mLoader = new AsyncTask<Void, Void, LoaderResult>() { 1757e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos @Override 1767e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos protected LoaderResult doInBackground(Void... params) { 1777e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return loadBitmap(currentUser, selectedUser); 1787e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1797e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1807e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos @Override 1817e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos protected void onPostExecute(LoaderResult result) { 1827e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos super.onPostExecute(result); 1837e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (isCancelled()) { 1847e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return; 1857e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1867e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (result.success) { 1877e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCached = true; 1887e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCache = result.bitmap; 189d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi mUpdateMonitor.setHasLockscreenWallpaper(result.bitmap != null); 1907e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mBar.updateMediaMetaData( 1917e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos true /* metaDataChanged */, true /* allowEnterAnimation */); 1927e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1937e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mLoader = null; 1947e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1957e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 1967e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1977e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1987e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos private static class LoaderResult { 1997e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos public final boolean success; 2007e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos public final Bitmap bitmap; 2017e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 2027e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos LoaderResult(boolean success, Bitmap bitmap) { 2037e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos this.success = success; 2047e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos this.bitmap = bitmap; 2057e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 2067e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 2077e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos static LoaderResult success(Bitmap b) { 2087e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return new LoaderResult(true, b); 2097e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 2107e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 2117e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos static LoaderResult fail() { 2127e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return new LoaderResult(false, null); 2137e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 214e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 2153b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2163b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos /** 2173b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos * Drawable that aligns left horizontally and center vertically (like ImageWallpaper). 2183b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos */ 2193b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos public static class WallpaperDrawable extends DrawableWrapper { 2203b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 221751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos private final ConstantState mState; 222751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos private final Rect mTmpRect = new Rect(); 2233b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2243b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos public WallpaperDrawable(Resources r, Bitmap b) { 225751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos this(r, new ConstantState(b)); 226751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 227751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 228751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos private WallpaperDrawable(Resources r, ConstantState state) { 229751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos super(new BitmapDrawable(r, state.mBackground)); 230751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos mState = state; 2313b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2323b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2333b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos @Override 234d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos public void setXfermode(@Nullable Xfermode mode) { 235d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos // DrawableWrapper does not call this for us. 236d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos getDrawable().setXfermode(mode); 237d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos } 238d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos 239d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos @Override 2403b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos public int getIntrinsicWidth() { 2413b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos return -1; 2423b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2433b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2443b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos @Override 2453b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos public int getIntrinsicHeight() { 2463b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos return -1; 2473b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2483b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2493b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos @Override 2503b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos protected void onBoundsChange(Rect bounds) { 2513b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos int vwidth = getBounds().width(); 2523b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos int vheight = getBounds().height(); 253751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos int dwidth = mState.mBackground.getWidth(); 254751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos int dheight = mState.mBackground.getHeight(); 2553b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos float scale; 2563b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos float dx = 0, dy = 0; 2573b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2583b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos if (dwidth * vheight > vwidth * dheight) { 2593b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos scale = (float) vheight / (float) dheight; 2603b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } else { 2613b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos scale = (float) vwidth / (float) dwidth; 2623b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2633b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2643b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos if (scale <= 1f) { 2653b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos scale = 1f; 2663b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2673b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos dy = (vheight - dheight * scale) * 0.5f; 2683b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2693b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos mTmpRect.set( 2703b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos bounds.left, 2713b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos bounds.top + Math.round(dy), 2723b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos bounds.left + Math.round(dwidth * scale), 2733b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos bounds.top + Math.round(dheight * scale + dy)); 2743b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2753b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos super.onBoundsChange(mTmpRect); 2763b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 277751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 278751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos @Override 279751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos public ConstantState getConstantState() { 280751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos return mState; 281751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 282751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 283751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos static class ConstantState extends Drawable.ConstantState { 284751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 285751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos private final Bitmap mBackground; 286751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 287751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos ConstantState(Bitmap background) { 288751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos mBackground = background; 289751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 290751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 291751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos @Override 292751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos public Drawable newDrawable() { 293751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos return newDrawable(null); 294751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 295751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 296751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos @Override 297751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos public Drawable newDrawable(@Nullable Resources res) { 298751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos return new WallpaperDrawable(res, this); 299751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 300751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 301751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos @Override 302751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos public int getChangingConfigurations() { 303751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos // DrawableWrapper already handles this for us. 304751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos return 0; 305751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 306751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 3073b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 308e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos} 309