壁纸显示流程
WallpaperManager 中可以通过 setBitmap setStream setResource 三种方式进行设置锁屏壁纸。
都是调用 WallpaperManagerService 的 setWallpaper 获取 ParcelFileDescriptor 对象
setBitmap:将当前系统壁纸更改为位图。 给定的位图被转换为 PNG 并存储为墙纸。 成功后,将广播意图 {@link Intent#ACTION_WALLPAPER_CHANGED}。
setStream:将当前系统壁纸更改为特定字节流。 给定的 InputStream 被复制到持久存储中,现在将用作墙纸。 目前它必须是 JPEG 或 PNG 图像。 成功后,将广播意图 {@link Intent#ACTION_WALLPAPER_CHANGED}。
setResource:将当前系统壁纸更改为给定资源中的位图。资源作为原始数据流打开并复制到壁纸中; 它必须是有效的 PNG 或 JPEG 图像。 成功后,将广播意图 {@link Intent#ACTION_WALLPAPER_CHANGED}。
setStream
setResource base/core/java/android/app/WallpaperManager.java
private void copyStreamToWallpaperFile(InputStream data, FileOutputStream fos)
throws IOException {
FileUtils.copy(data, fos);//获取壁纸,写入存储路径
}
@RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public int setStream(InputStream bitmapData, Rect visibleCropHint,
boolean allowBackup, @SetWallpaperFlags int which)
throws IOException {
validateRect(visibleCropHint);
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
}
final Bundle result = new Bundle();
final WallpaperSetCompletion completion = new WallpaperSetCompletion();
try {
//sGlobals.mService--WallpaperManagerService
ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
mContext.getOpPackageName(), visibleCropHint, allowBackup,
result, which, completion, mContext.getUserId());
if (fd != null) {
FileOutputStream fos = null;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
//将壁纸copy一份存储到对应目录
copyStreamToWallpaperFile(bitmapData, fos);
fos.close();
completion.waitForCompletion();
} finally {
IoUtils.closeQuietly(fos);
}
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
}
@RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public int setResource(@RawRes int resid, @SetWallpaperFlags int which)
throws IOException {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
}
final Bundle result = new Bundle();
final WallpaperSetCompletion completion = new WallpaperSetCompletion();
try {
Resources resources = mContext.getResources();
/* Set the wallpaper to the default values */
ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(
"res:" + resources.getResourceName(resid),
mContext.getOpPackageName(), null, false, result, which, completion,
mContext.getUserId());
if (fd != null) {
FileOutputStream fos = null;
boolean ok = false;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
// The 'close()' is the trigger for any server-side image manipulation,
// so we must do that before waiting for completion.
fos.close();
completion.waitForCompletion();
} finally {
// Might be redundant but completion shouldn't wait unless the write
// succeeded; this is a fallback if it threw past the close+wait.
IoUtils.closeQuietly(fos);
}
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public int setBitmap(Bitmap fullImage, Rect visibleCropHint,
boolean allowBackup, @SetWallpaperFlags int which, int userId)
throws IOException {
validateRect(visibleCropHint);
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
}
final Bundle result = new Bundle();
final WallpaperSetCompletion completion = new WallpaperSetCompletion();
try {
ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
mContext.getOpPackageName(), visibleCropHint, allowBackup,
result, which, completion, userId);
if (fd != null) {
FileOutputStream fos = null;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
fullImage.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
completion.waitForCompletion();
} finally {
IoUtils.closeQuietly(fos);
}
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
}
base\services\core\java\com\android\server\wallpaper\WallpaperManagerService.java
setWallpaper通过 getWallpaperSafeLocked 获取系统服务 systemReady() 启动初始化的 WallpaperData
public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Rect cropHint, boolean allowBackup, Bundle extras, int which,
IWallpaperManagerCallback completion, int userId) {
userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
false /* all */, true /* full */, "changing wallpaper", null /* pkg */);
//检查设置壁纸权限
checkPermission(android.Manifest.permission.SET_WALLPAPER);
//which:FLAG_LOCK=2锁屏壁纸;FLAG_SYSTEM=1桌面壁纸
if ((which & (FLAG_LOCK|FLAG_SYSTEM)) == 0) {
final String msg = "Must specify a valid wallpaper category to set";
Slog.e(TAG, msg);
throw new IllegalArgumentException(msg);
}
if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
return null;
}
// "null" means the no-op crop, preserving the full input image
if (cropHint == null) {
cropHint = new Rect(0, 0, 0, 0);
} else {
if (cropHint.width() < 0 || cropHint.height() < 0
|| cropHint.left < 0
|| cropHint.top < 0) {
throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);
}
}
synchronized (mLock) {
if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
WallpaperData wallpaper;
/* If we're setting system but not lock, and lock is currently sharing the system
* wallpaper, we need to migrate that image over to being lock-only before
* the caller here writes new bitmap data.
*/
//正在设置桌面壁纸,但是桌面壁纸和锁屏壁纸相同,在写入新的位图数据之前,要将壁纸设置为仅锁屏
if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {
Slog.i(TAG, "Migrating current wallpaper to be lock-only before"
+ "updating system wallpaper");
migrateSystemToLockWallpaperLocked(userId);
}
wallpaper = getWallpaperSafeLocked(userId, which);
final long ident = Binder.clearCallingIdentity();
try {
ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
if (pfd != null) {
wallpaper.imageWallpaperPending = true;
wallpaper.whichPending = which;
wallpaper.setComplete = completion;
wallpaper.cropHint.set(cropHint);
wallpaper.allowBackup = allowBackup;
}
return pfd;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
base\services\core\java\com\android\server\wallpaper\WallpaperManagerService.java
获取 WallpaperData 的 ParcelFileDescriptor 返回给 WallpaperManager 。ParcelFileDescriptor 继续进行 copyStreamToWallpaperFile 写入覆盖操作,替换壁纸文件。
ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
Bundle extras) {
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);
}
ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
Slog.w(TAG, "restorecon failed for wallpaper file: " +
wallpaper.wallpaperFile.getPath());
return null;
}
wallpaper.name = name;
wallpaper.wallpaperId = makeWallpaperIdLocked();
if (extras != null) {
extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
}
// Nullify field to require new computation
wallpaper.primaryColors = null;
Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
+ " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
return fd;
} catch (FileNotFoundException e) {
Slog.w(TAG, "Error setting wallpaper", e);
}
return null;
}
base/core/java/android/os/ParcelFileDescriptor.java
//在ParcelFileDescriptor上创建的OutputStream,它会在流关闭时调用ParcelFileDescriptor.close()
public static class AutoCloseOutputStream extends FileOutputStream {
private final ParcelFileDescriptor mPfd;
public AutoCloseOutputStream(ParcelFileDescriptor pfd) {
super(pfd.getFileDescriptor());
mPfd = pfd;
}
@Override
public void close() throws IOException {
try {
super.close();
} finally {
mPfd.close();
}
}
}
base\services\core\java\com\android\server\wallpaper\WallpaperManagerService.java
WallpaperObserver是WallpaperManagerservice.java的内部类
* 监听壁纸的变化并通知所有 IWallpaperServiceCallbacks 壁纸已更改。
* CREATE 在没有设置壁纸时触发,并且是第一次创建。
* 每次更换壁纸都会触发 CLOSE_WRITE
文件的变化触发 WallpaperObserver 的 onEvent()
public void onEvent(int event, String path) {
if (path == null) {
return;
}
final boolean moved = (event == MOVED_TO);
final boolean written = (event == CLOSE_WRITE || moved);
final File changedFile = new File(mWallpaperDir, path);
// System and system+lock changes happen on the system wallpaper input file;
// lock-only changes happen on the dedicated lock wallpaper input file
final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
int notifyColorsWhich = 0;
WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
if (DEBUG) {
Slog.v(TAG, "Wallpaper file change: evt=" + event
+ " path=" + path
+ " sys=" + sysWallpaperChanged
+ " lock=" + lockWallpaperChanged
+ " imagePending=" + wallpaper.imageWallpaperPending
+ " whichPending=0x" + Integer.toHexString(wallpaper.whichPending)
+ " written=" + written);
}
//锁屏壁纸变化
if (moved && lockWallpaperChanged) {
// We just migrated sys -> lock to preserve imagery for an impending
// new system-only wallpaper. Tell keyguard about it and make sure it
// has the right SELinux label.
if (DEBUG) {
Slog.i(TAG, "Sys -> lock MOVED_TO");
}
SELinux.restorecon(changedFile);
//壁纸变化
notifyLockWallpaperChanged();
//壁纸与锁屏图标反色问题
notifyWallpaperColorsChanged(wallpaper, FLAG_LOCK);
return;
}
synchronized (mLock) {
if (sysWallpaperChanged || lockWallpaperChanged) {
notifyCallbacksLocked(wallpaper);
if (wallpaper.wallpaperComponent == null
|| event != CLOSE_WRITE // includes the MOVED_TO case
|| wallpaper.imageWallpaperPending) {
if (written) {
// The image source has finished writing the source image,
// so we now produce the crop rect (in the background), and
// only publish the new displayable (sub)image as a result
// of that work.
if (DEBUG) {
Slog.v(TAG, "Wallpaper written; generating crop");
}
SELinux.restorecon(changedFile);
if (moved) {
// This is a restore, so generate the crop using any just-restored new
// crop guidelines, making sure to preserve our local dimension hints.
// We also make sure to reapply the correct SELinux label.
if (DEBUG) {
Slog.v(TAG, "moved-to, therefore restore; reloading metadata");
}
loadSettingsLocked(wallpaper.userId, true);
}
generateCrop(wallpaper);
if (DEBUG) {
Slog.v(TAG, "Crop done; invoking completion callback");
}
wallpaper.imageWallpaperPending = false;
if (sysWallpaperChanged) {
// If this was the system wallpaper, rebind...
bindWallpaperComponentLocked(mImageWallpaper, true,
false, wallpaper, null);
notifyColorsWhich |= FLAG_SYSTEM;
}
if (lockWallpaperChanged
|| (wallpaper.whichPending & FLAG_LOCK) != 0) {
if (DEBUG) {
Slog.i(TAG, "Lock-relevant wallpaper changed");
}
// either a lock-only wallpaper commit or a system+lock event.
// if it's system-plus-lock we need to wipe the lock bookkeeping;
// we're falling back to displaying the system wallpaper there.
if (!lockWallpaperChanged) {
mLockWallpaperMap.remove(wallpaper.userId);
}
// and in any case, tell keyguard about it
notifyLockWallpaperChanged();
notifyColorsWhich |= FLAG_LOCK;
}
saveSettingsLocked(wallpaper.userId);
// Publish completion *after* we've persisted the changes
if (wallpaper.setComplete != null) {
try {
wallpaper.setComplete.onWallpaperChanged();
} catch (RemoteException e) {
// if this fails we don't really care; the setting app may just
// have crashed and that sort of thing is a fact of life.
}
}
}
}
}
}
// Outside of the lock since it will synchronize itself
if (notifyColorsWhich != 0) {
notifyWallpaperColorsChanged(wallpaper, notifyColorsWhich);
}
}
}
cb 就是 LockscreenWallpaper,LockscreenWallpaper继承了IWallpaperManagerCallback重写了它的onWallppaerChanged方法。
iWallpaperManager.setLockWallpaperCallback(this);
void notifyLockWallpaperChanged() {
final IWallpaperManagerCallback cb = mKeyguardListener;
if (cb != null) {
try {
cb.onWallpaperChanged();
} catch (RemoteException e) {
// Oh well it went away; no big deal
}
}
}
@Override
public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
synchronized (mLock) {
mKeyguardListener = cb;
}
return true;
}
base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
public LockscreenWallpaper(WallpaperManager wallpaperManager,
@Nullable IWallpaperManager iWallpaperManager,
KeyguardUpdateMonitor keyguardUpdateMonitor,
DumpManager dumpManager,
NotificationMediaManager mediaManager,
@Main Handler mainHandler) {
dumpManager.registerDumpable(getClass().getSimpleName(), this);
mWallpaperManager = wallpaperManager;
mCurrentUserId = ActivityManager.getCurrentUser();
mUpdateMonitor = keyguardUpdateMonitor;
mMediaManager = mediaManager;
mH = mainHandler;
if (iWallpaperManager != null) {
// Service is disabled on some devices like Automotive
try {
iWallpaperManager.setLockWallpaperCallback(this);//赋值
} catch (RemoteException e) {
Log.e(TAG, "System dead?" + e);
}
}
}
onWallppaerChanged
public void onWallpaperChanged() {
// Called on Binder thread.
postUpdateWallpaper();
}
private void postUpdateWallpaper() {
if (mH == null) {
Log.wtfStack(TAG, "Trying to use LockscreenWallpaper before initialization.");
return;
}
mH.removeCallbacks(this);
mH.post(this);
}
LockscreenWallpaper 中具体执行在其 run() 函数,完成锁屏壁纸替换操作。
public void run() {
// Called in response to onWallpaperChanged on the main thread.
if (mLoader != null) {
mLoader.cancel(false /* interrupt */);
}
final int currentUser = mCurrentUserId;
final UserHandle selectedUser = mSelectedUser;
mLoader = new AsyncTask<Void, Void, LoaderResult>() {
@Override
protected LoaderResult doInBackground(Void... params) {
return loadBitmap(currentUser, selectedUser);
}
@Override
protected void onPostExecute(LoaderResult result) {
super.onPostExecute(result);
if (isCancelled()) {
return;
}
if (result.success) {
mCached = true;
mCache = result.bitmap;
mUpdateMonitor.setHasLockscreenWallpaper(result.bitmap != null);
//通知StatusBar更新壁纸
mMediaManager.updateMediaMetaData(
true /* metaDataChanged */, true /* allowEnterAnimation */);
}
mLoader = null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
异步获取壁纸,并通知StatusBar去更新壁纸。对锁屏壁纸所在view做setImageBitmap。
/**
* Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
*/
public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
Trace.beginSection("StatusBar#updateMediaMetaData");
if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) {
Trace.endSection();
return;
}
if (mBackdrop == null) {
Trace.endSection();
return; // called too early
}
boolean wakeAndUnlock = mBiometricUnlockController != null
&& mBiometricUnlockController.isWakeAndUnlock();
if (mKeyguardStateController.isLaunchTransitionFadingAway() || wakeAndUnlock) {
mBackdrop.setVisibility(View.INVISIBLE);
Trace.endSection();
return;
}
MediaMetadata mediaMetadata = getMediaMetadata();
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: updating album art for notification "
+ getMediaNotificationKey()
+ " metadata=" + mediaMetadata
+ " metaDataChanged=" + metaDataChanged
+ " state=" + mStatusBarStateController.getState());
}
Bitmap artworkBitmap = null;
if (mediaMetadata != null && !mKeyguardBypassController.getBypassEnabled()) {
artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
if (artworkBitmap == null) {
artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
}
}
// Process artwork on a background thread and send the resulting bitmap to
// finishUpdateMediaMetaData.
//在后台线程上处理图稿并将生成的位图发送到finishUpdateMediaMetaData。
if (metaDataChanged) {
for (AsyncTask<?, ?, ?> task : mProcessArtworkTasks) {
task.cancel(true);
}
mProcessArtworkTasks.clear();
}
if (artworkBitmap != null && !Utils.useQsMediaPlayer(mContext)) {
mProcessArtworkTasks.add(new ProcessArtworkTask(this, metaDataChanged,
allowEnterAnimation).execute(artworkBitmap));
} else {
finishUpdateMediaMetaData(metaDataChanged, allowEnterAnimation, null);
}
Trace.endSection();
}
setImageBitmap
private void finishUpdateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation,
@Nullable Bitmap bmp) {
Drawable artworkDrawable = null;
if (bmp != null) {
artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), bmp);
}
boolean hasMediaArtwork = artworkDrawable != null;
boolean allowWhenShade = false;
if (ENABLE_LOCKSCREEN_WALLPAPER && artworkDrawable == null) {
Bitmap lockWallpaper =
mLockscreenWallpaper != null ? mLockscreenWallpaper.getBitmap() : null;
if (lockWallpaper != null) {
artworkDrawable = new LockscreenWallpaper.WallpaperDrawable(
mBackdropBack.getResources(), lockWallpaper);
// We're in the SHADE mode on the SIM screen - yet we still need to show
// the lockscreen wallpaper in that mode.
allowWhenShade = mStatusBarStateController.getState() == KEYGUARD;
}
}
NotificationShadeWindowController windowController =
mNotificationShadeWindowController.get();
boolean hideBecauseOccluded = mStatusBarLazy.get().isOccluded();
final boolean hasArtwork = artworkDrawable != null;
mColorExtractor.setHasMediaArtwork(hasMediaArtwork);
if (mScrimController != null) {
mScrimController.setHasBackdrop(hasArtwork);
}
if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK)
&& (mStatusBarStateController.getState() != StatusBarState.SHADE || allowWhenShade)
&& mBiometricUnlockController != null && mBiometricUnlockController.getMode()
!= BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
&& !hideBecauseOccluded) {
// time to show some art!
if (mBackdrop.getVisibility() != View.VISIBLE) {
mBackdrop.setVisibility(View.VISIBLE);
if (allowEnterAnimation) {
mBackdrop.setAlpha(0);
mBackdrop.animate().alpha(1f);
} else {
mBackdrop.animate().cancel();
mBackdrop.setAlpha(1f);
}
if (windowController != null) {
windowController.setBackdropShowing(true);
}
metaDataChanged = true;
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
}
}
if (metaDataChanged) {
if (mBackdropBack.getDrawable() != null) {
Drawable drawable =
mBackdropBack.getDrawable().getConstantState()
.newDrawable(mBackdropFront.getResources()).mutate();
mBackdropFront.setImageDrawable(drawable);
mBackdropFront.setAlpha(1f);
mBackdropFront.setVisibility(View.VISIBLE);
} else {
mBackdropFront.setVisibility(View.INVISIBLE);
}
if (DEBUG_MEDIA_FAKE_ARTWORK) {
final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF);
Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c));
mBackdropBack.setBackgroundColor(0xFFFFFFFF);
mBackdropBack.setImageDrawable(new ColorDrawable(c));
} else {
mBackdropBack.setImageDrawable(artworkDrawable);
}
if (mBackdropFront.getVisibility() == View.VISIBLE) {
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from "
+ mBackdropFront.getDrawable()
+ " to "
+ mBackdropBack.getDrawable());
}
mBackdropFront.animate()
.setDuration(250)
.alpha(0f).withEndAction(mHideBackdropFront);
}
}
} else {
// need to hide the album art, either because we are unlocked, on AOD
// or because the metadata isn't there to support it
if (mBackdrop.getVisibility() != View.GONE) {
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
}
boolean cannotAnimateDoze = mStatusBarStateController.isDozing()
&& !ScrimState.AOD.getAnimateChange();
boolean needsBypassFading = mKeyguardStateController.isBypassFadingAnimation();
if (((mBiometricUnlockController != null && mBiometricUnlockController.getMode()
== BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
|| cannotAnimateDoze) && !needsBypassFading)
|| hideBecauseOccluded) {
// We are unlocking directly - no animation!
mBackdrop.setVisibility(View.GONE);
mBackdropBack.setImageDrawable(null);
if (windowController != null) {
windowController.setBackdropShowing(false);
}
} else {
if (windowController != null) {
windowController.setBackdropShowing(false);
}
mBackdrop.animate()
.alpha(0)
.setInterpolator(Interpolators.ACCELERATE_DECELERATE)
.setDuration(300)
.setStartDelay(0)
.withEndAction(() -> {
mBackdrop.setVisibility(View.GONE);
mBackdropFront.animate().cancel();
mBackdropBack.setImageDrawable(null);
mMainExecutor.execute(mHideBackdropFront);
});
if (mKeyguardStateController.isKeyguardFadingAway()) {
mBackdrop.animate()
.setDuration(
mKeyguardStateController.getShortenedFadingAwayDuration())
.setStartDelay(
mKeyguardStateController.getKeyguardFadingAwayDelay())
.setInterpolator(Interpolators.LINEAR)
.start();
}
}
}
}
}
关联背景与控件
public void setup(BackDropView backdrop, ImageView backdropFront, ImageView backdropBack,
ScrimController scrimController, LockscreenWallpaper lockscreenWallpaper) {
mBackdrop = backdrop;
mBackdropFront = backdropFront;
mBackdropBack = backdropBack;
mScrimController = scrimController;
mLockscreenWallpaper = lockscreenWallpaper;
}
base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
在StatusBar中将图片设置到View中
NotificationMediaManager mMediaManager
mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper);
到此,锁屏壁纸就设置成功了。