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; 39ea1fb1e077e9fa8ce6a8a9e8caaf7423dc09cc9dLucas Dupinimport android.app.WallpaperColors; 40e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport android.util.Log; 41e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 42d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggiimport com.android.keyguard.KeyguardUpdateMonitor; 43d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi 44e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roosimport libcore.io.IoUtils; 45e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 4612a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshevimport java.util.Objects; 4712a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev 48e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos/** 49e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos * Manages the lockscreen wallpaper. 50e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos */ 51e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roospublic class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implements Runnable { 52e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 53e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos private static final String TAG = "LockscreenWallpaper"; 54e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 552a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk private final StatusBar mBar; 5612a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev private final WallpaperManager mWallpaperManager; 57e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos private final Handler mH; 58d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi private final KeyguardUpdateMonitor mUpdateMonitor; 59e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 60e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos private boolean mCached; 61e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos private Bitmap mCache; 6212a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev private int mCurrentUserId; 6312a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev // The user selected in the UI, or null if no user is selected or UI doesn't support selecting 6412a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev // users. 6512a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev private UserHandle mSelectedUser; 667e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos private AsyncTask<Void, Void, LoaderResult> mLoader; 67e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 682a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk public LockscreenWallpaper(Context ctx, StatusBar bar, Handler h) { 69e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos mBar = bar; 70e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos mH = h; 7112a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE); 7212a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev mCurrentUserId = ActivityManager.getCurrentUser(); 73d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi mUpdateMonitor = KeyguardUpdateMonitor.getInstance(ctx); 74e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 757e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos IWallpaperManager service = IWallpaperManager.Stub.asInterface( 767e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos ServiceManager.getService(Context.WALLPAPER_SERVICE)); 77e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos try { 787e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos service.setLockWallpaperCallback(this); 79e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } catch (RemoteException e) { 80e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos Log.e(TAG, "System dead?" + e); 81e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 82e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 83e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 84e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos public Bitmap getBitmap() { 857e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (mCached) { 867e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return mCache; 877e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 887e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (!mWallpaperManager.isWallpaperSupported()) { 897e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCached = true; 907e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCache = null; 917e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return null; 927e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 937e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 947e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos LoaderResult result = loadBitmap(mCurrentUserId, mSelectedUser); 957e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (result.success) { 967e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCached = true; 97d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi mUpdateMonitor.setHasLockscreenWallpaper(result.bitmap != null); 987e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCache = result.bitmap; 997e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1007e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return mCache; 1017e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1027e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1037e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos public LoaderResult loadBitmap(int currentUserId, UserHandle selectedUser) { 1047e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos // May be called on any thread - only use thread safe operations. 1057e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1067e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK 1077e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos // wallpaper. 1087e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos final int lockWallpaperUserId = 1097e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos selectedUser != null ? selectedUser.getIdentifier() : currentUserId; 1107e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos ParcelFileDescriptor fd = mWallpaperManager.getWallpaperFile( 1117e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos WallpaperManager.FLAG_LOCK, lockWallpaperUserId); 1127e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1137e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (fd != null) { 1147e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos try { 1157e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos BitmapFactory.Options options = new BitmapFactory.Options(); 1167e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return LoaderResult.success(BitmapFactory.decodeFileDescriptor( 1177e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos fd.getFileDescriptor(), null, options)); 1187e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } catch (OutOfMemoryError e) { 1197e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos Log.w(TAG, "Can't decode file", e); 1207e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return LoaderResult.fail(); 1217e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } finally { 1227e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos IoUtils.closeQuietly(fd); 123e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 1247e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } else { 1254324f9f2476afc08e41700faa23ee33881d0d3b8Evan Rosky if (selectedUser != null) { 1264324f9f2476afc08e41700faa23ee33881d0d3b8Evan Rosky // Show the selected user's static wallpaper. 127049978e61d99ad68e3acac16f0f3801d1eeedad6Lucas Dupin return LoaderResult.success(mWallpaperManager.getBitmapAsUser( 128049978e61d99ad68e3acac16f0f3801d1eeedad6Lucas Dupin selectedUser.getIdentifier(), true /* hardware */)); 1297e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 130e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } else { 1314324f9f2476afc08e41700faa23ee33881d0d3b8Evan Rosky // When there is no selected user, show the system wallpaper 1327e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return LoaderResult.success(null); 133e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 134e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 135e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 136e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 13712a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev public void setCurrentUser(int user) { 13812a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev if (user != mCurrentUserId) { 13913a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky if (mSelectedUser == null || user != mSelectedUser.getIdentifier()) { 14013a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky mCached = false; 14113a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky } 14212a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev mCurrentUserId = user; 143e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 144e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 145e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 14612a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev public void setSelectedUser(UserHandle selectedUser) { 14712a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev if (Objects.equals(selectedUser, mSelectedUser)) { 14812a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev return; 14912a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev } 15012a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev mSelectedUser = selectedUser; 1517e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos postUpdateWallpaper(); 15212a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev } 15312a30e8874cedbc7f0cc3a7ec6821bc42de3280eVadim Tryshev 154e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos @Override 155e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos public void onWallpaperChanged() { 156e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos // Called on Binder thread. 1577e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos postUpdateWallpaper(); 1587e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1597e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 160ea1fb1e077e9fa8ce6a8a9e8caaf7423dc09cc9dLucas Dupin @Override 16150ba991655555dfde90149489f6485a0529ba0acLucas Dupin public void onWallpaperColorsChanged(WallpaperColors colors, int which, int userId) { 162ea1fb1e077e9fa8ce6a8a9e8caaf7423dc09cc9dLucas Dupin 163ea1fb1e077e9fa8ce6a8a9e8caaf7423dc09cc9dLucas Dupin } 164ea1fb1e077e9fa8ce6a8a9e8caaf7423dc09cc9dLucas Dupin 1657e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos private void postUpdateWallpaper() { 166e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos mH.removeCallbacks(this); 167e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos mH.post(this); 168e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 169e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos 170e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos @Override 171e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos public void run() { 172e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos // Called in response to onWallpaperChanged on the main thread. 1737e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1747e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (mLoader != null) { 1757e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mLoader.cancel(false /* interrupt */); 1767e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1777e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1787e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos final int currentUser = mCurrentUserId; 1797e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos final UserHandle selectedUser = mSelectedUser; 1807e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mLoader = new AsyncTask<Void, Void, LoaderResult>() { 1817e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos @Override 1827e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos protected LoaderResult doInBackground(Void... params) { 1837e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return loadBitmap(currentUser, selectedUser); 1847e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1857e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 1867e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos @Override 1877e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos protected void onPostExecute(LoaderResult result) { 1887e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos super.onPostExecute(result); 1897e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (isCancelled()) { 1907e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return; 1917e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1927e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos if (result.success) { 1937e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCached = true; 1947e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mCache = result.bitmap; 195d11d1a9486d44b98e28b70c25711ebfc283b746eJorim Jaggi mUpdateMonitor.setHasLockscreenWallpaper(result.bitmap != null); 1967e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mBar.updateMediaMetaData( 1977e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos true /* metaDataChanged */, true /* allowEnterAnimation */); 1987e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 1997e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos mLoader = null; 2007e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 2017e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 2027e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 2037e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 2047e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos private static class LoaderResult { 2057e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos public final boolean success; 2067e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos public final Bitmap bitmap; 2077e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 2087e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos LoaderResult(boolean success, Bitmap bitmap) { 2097e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos this.success = success; 2107e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos this.bitmap = bitmap; 2117e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 2127e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 2137e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos static LoaderResult success(Bitmap b) { 2147e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return new LoaderResult(true, b); 2157e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 2167e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos 2177e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos static LoaderResult fail() { 2187e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos return new LoaderResult(false, null); 2197e9dec284128ef07024c85bc59f317f3e6726c23Adrian Roos } 220e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos } 2213b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2223b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos /** 2233b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos * Drawable that aligns left horizontally and center vertically (like ImageWallpaper). 2243b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos */ 2253b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos public static class WallpaperDrawable extends DrawableWrapper { 2263b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 227751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos private final ConstantState mState; 228751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos private final Rect mTmpRect = new Rect(); 2293b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2303b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos public WallpaperDrawable(Resources r, Bitmap b) { 231751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos this(r, new ConstantState(b)); 232751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 233751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 234751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos private WallpaperDrawable(Resources r, ConstantState state) { 235751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos super(new BitmapDrawable(r, state.mBackground)); 236751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos mState = state; 2373b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2383b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2393b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos @Override 240d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos public void setXfermode(@Nullable Xfermode mode) { 241d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos // DrawableWrapper does not call this for us. 242d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos getDrawable().setXfermode(mode); 243d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos } 244d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos 245d866b02d5435108db41c8f4a68175c52ca319c55Adrian Roos @Override 2463b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos public int getIntrinsicWidth() { 2473b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos return -1; 2483b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2493b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2503b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos @Override 2513b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos public int getIntrinsicHeight() { 2523b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos return -1; 2533b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2543b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2553b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos @Override 2563b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos protected void onBoundsChange(Rect bounds) { 2573b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos int vwidth = getBounds().width(); 2583b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos int vheight = getBounds().height(); 259751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos int dwidth = mState.mBackground.getWidth(); 260751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos int dheight = mState.mBackground.getHeight(); 2613b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos float scale; 2623b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos float dx = 0, dy = 0; 2633b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2643b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos if (dwidth * vheight > vwidth * dheight) { 2653b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos scale = (float) vheight / (float) dheight; 2663b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } else { 2673b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos scale = (float) vwidth / (float) dwidth; 2683b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2693b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2703b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos if (scale <= 1f) { 2713b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos scale = 1f; 2723b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 2733b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos dy = (vheight - dheight * scale) * 0.5f; 2743b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2753b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos mTmpRect.set( 2763b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos bounds.left, 2773b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos bounds.top + Math.round(dy), 2783b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos bounds.left + Math.round(dwidth * scale), 2793b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos bounds.top + Math.round(dheight * scale + dy)); 2803b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos 2813b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos super.onBoundsChange(mTmpRect); 2823b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 283751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 284751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos @Override 285751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos public ConstantState getConstantState() { 286751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos return mState; 287751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 288751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 289751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos static class ConstantState extends Drawable.ConstantState { 290751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 291751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos private final Bitmap mBackground; 292751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 293751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos ConstantState(Bitmap background) { 294751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos mBackground = background; 295751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 296751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 297751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos @Override 298751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos public Drawable newDrawable() { 299751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos return newDrawable(null); 300751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 301751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 302751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos @Override 303751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos public Drawable newDrawable(@Nullable Resources res) { 304751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos return new WallpaperDrawable(res, this); 305751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 306751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos 307751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos @Override 308751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos public int getChangingConfigurations() { 309751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos // DrawableWrapper already handles this for us. 310751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos return 0; 311751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 312751f33f8c73892a34f99eb0f4c8266b87a331283Adrian Roos } 3133b777cb9b18c3e6f8549cd25695600cd7dd3010bAdrian Roos } 314e381c169fc445b961a131ea5553150d4c44f0c9eAdrian Roos} 315