0
点赞
收藏
分享

微信扫一扫

Android-Keyguard Wallpaper

扒皮狼 2022-01-06 阅读 110
androidjava

壁纸显示流程

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);

到此,锁屏壁纸就设置成功了。

举报

相关推荐

0 条评论