Android14 系统Wallpaper详解之ImageWallpaper

./frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java

./frameworks/base/core/java/android/service/wallpaper/WallpaperService.java

  1. ImageWallpaper是Android的默认壁纸服务

  2. ImageWallpaper集成了WallpaperService,WallpaperService是所有壁纸服务的基类,使用模板模式定义了壁纸服务的主要相关流程,子类根据自身需要去实现具体的自己特有的方法部分

  3. 壁纸服务的基本功能无外乎两点,一是获取壁纸;另一个是绘制壁纸。WallpaperService定义了一个内部类Engine,将壁纸的获取和绘制都委托给了它,所以具体的壁纸服务子类的主要任务就是实现该类

    1. ImageWallpaper的Engine
    @Override
    public Engine onCreateEngine() {
        return new CanvasEngine();
    }
    
    1. 该方法创建一个CanvasEngine实例,并将其返回,父类WallpaperService通过该方法拿到子类具体的Engine,然后实现壁纸的自定义获取和显示

1、CanvasEngine介绍

./frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java

集成自WallpaperService.Engine

class CanvasEngine extends WallpaperService.Engine implements DisplayListener {
        private WallpaperManager mWallpaperManager;
        private final WallpaperLocalColorExtractor mWallpaperLocalColorExtractor;
        private SurfaceHolder mSurfaceHolder;
}

CanvasEngine是ImageWallpaper实现的用于执行具体的壁纸绘制相关逻辑的执行者。其重写了父类Engine的一些方法来实现自定义的行为。

按照顺序执行,CanvasEngine先执行onCreate方法,并在改方法内部根据设备的相关信息初始化相关参数

//在WallpaperService的onBind方法执行时,会触发改方法的执行。
//用于获取设备尺寸,然后根据该信息更新相关尺寸参数
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
    Trace.beginSection("ImageWallpaper.CanvasEngine#onCreate");
    if (DEBUG) {
        Log.d(TAG, "onCreate");
    }
    mWallpaperManager = getDisplayContext().getSystemService(WallpaperManager.class);
    mIsLockscreenLiveWallpaperEnabled = mWallpaperManager
            .isLockscreenLiveWallpaperEnabled();
    //mSurfaceHolder 赋值
    mSurfaceHolder = surfaceHolder;
    Rect dimensions = mIsLockscreenLiveWallpaperEnabled
            ? mWallpaperManager.peekBitmapDimensions(getSourceFlag(), true)
            : mWallpaperManager.peekBitmapDimensions();
    int width = Math.max(MIN_SURFACE_WIDTH, dimensions.width());
    int height = Math.max(MIN_SURFACE_HEIGHT, dimensions.height());
    //使用上面获得的尺寸来更新SurfaceHolder
    mSurfaceHolder.setFixedSize(width, height);

    getDisplayContext().getSystemService(DisplayManager.class)
            .registerDisplayListener(this, null);
    getDisplaySizeAndUpdateColorExtractor();
    Trace.endSection();
}

drawFrame方法

private void drawFrame() {
    MyLog.d("drawFrame");
    mLongExecutor.execute(this::drawFrameSynchronized);
}

private void drawFrameSynchronized() {
    synchronized (mLock) {
        drawFrameInternal();
    }
}

private void drawFrameInternal() {
    MyLog.d("drawFrameInternal");
    if (mSurfaceHolder == null) {
        Log.e(TAG, "attempt to draw a frame without a valid surface");
        return;
    }

    // load the wallpaper if not already done
    if (!isBitmapLoaded()) {
        //加载壁纸
        loadWallpaperAndDrawFrameInternal();
    } else {
        mBitmapUsages++;
        //绘制壁纸
        drawFrameOnCanvas(mBitmap);
        reportEngineShown(false);
        //清空壁纸
        unloadBitmapIfNotUsedInternal();
    }
}

loadWallpaperAndDrawFrameInternal,该方法会首先尝试通过WallpaperManager来获取壁纸,如果获取失败,则在清空壁纸缓存后再次尝试,如果依然失败,则返回null

private void loadWallpaperAndDrawFrameInternal() {
    Trace.beginSection("ImageWallpaper.CanvasEngine#loadWallpaper");
    boolean loadSuccess = false;
    Bitmap bitmap;
    try {
        bitmap = mIsLockscreenLiveWallpaperEnabled
                ? mWallpaperManager.getBitmapAsUser(
                        mUserTracker.getUserId(), false, getSourceFlag(), true)
                : mWallpaperManager.getBitmapAsUser(mUserTracker.getUserId(), false);
        if (bitmap != null
                && bitmap.getByteCount() > RecordingCanvas.MAX_BITMAP_SIZE) {
            throw new RuntimeException("Wallpaper is too large to draw!");
        }
    } catch (RuntimeException | OutOfMemoryError exception) {

        // Note that if we do fail at this, and the default wallpaper can't
        // be loaded, we will go into a cycle. Don't do a build where the
        // default wallpaper can't be loaded.
        Log.w(TAG, "Unable to load wallpaper!", exception);
        if (mIsLockscreenLiveWallpaperEnabled) {
            mWallpaperManager.clearWallpaper(getWallpaperFlags(), mUserTracker.getUserId());
        } else {
            mWallpaperManager.clearWallpaper(
                    WallpaperManager.FLAG_SYSTEM, mUserTracker.getUserId());
        }

        try {
            bitmap = mIsLockscreenLiveWallpaperEnabled
                    ? mWallpaperManager.getBitmapAsUser(
                            mUserTracker.getUserId(), false, getSourceFlag(), true)
                    : mWallpaperManager.getBitmapAsUser(mUserTracker.getUserId(), false);
        } catch (RuntimeException | OutOfMemoryError e) {
            Log.w(TAG, "Unable to load default wallpaper!", e);
            bitmap = null;
        }
    }

    if (bitmap == null) {
        Log.w(TAG, "Could not load bitmap");
    } else if (bitmap.isRecycled()) {
        Log.e(TAG, "Attempt to load a recycled bitmap");
    } else if (mBitmap == bitmap) {
        Log.e(TAG, "Loaded a bitmap that was already loaded");
    } else {
        // at this point, loading is done correctly.
        loadSuccess = true;
        // recycle the previously loaded bitmap
        if (mBitmap != null) {
            mBitmap.recycle();
        }
        mBitmap = bitmap;
        mWideColorGamut = mIsLockscreenLiveWallpaperEnabled
                ? mWallpaperManager.wallpaperSupportsWcg(getSourceFlag())
                : mWallpaperManager.wallpaperSupportsWcg(WallpaperManager.FLAG_SYSTEM);

        // +2 usages for the color extraction and the delayed unload.
        mBitmapUsages += 2;
        recomputeColorExtractorMiniBitmap();
        drawFrameInternal();

        /*
         * after loading, the bitmap will be unloaded after all these conditions:
         *   - the frame is redrawn
         *   - the mini bitmap from color extractor is recomputed
         *   - the DELAY_UNLOAD_BITMAP has passed
         */
        mLongExecutor.executeDelayed(
                this::unloadBitmapIfNotUsedSynchronized, DELAY_UNLOAD_BITMAP);
    }
    // even if the bitmap cannot be loaded, call reportEngineShown
    if (!loadSuccess) rep
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值