wallpaper

设置壁纸

void changeWallpaper(Bitmap targetBitmap) {
    WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
    wallpaperManager.setBitmap(targetBitmap);
}

wallpapermanager和 wallpaperManagerService

WallpaperManager {
    static WallpaperManager getInstance(Context context) {
        return context.getSystemService(Context.WALLPAPER_SERVICE);
    }
}

ContextImpl的getSystemService,最后会调用SystemServiceRegistry.getSystemService(String name)

从ServiceManager获取wallpaperManagerService的binder,缓存到这个Registry里。

SystemServiceRegistry {
    static {
        registerService(Context.WALLPAPER_SERVICE, WallpaperManager.class,
            new CacheServiceFetcher<WallpaperManager>() {
                WallpaperManager createService(ContextImpl ctx) {
                    IBinder b;
                    b = ServiceManager.getServiceOrThrow(Context.WALLPAPER_SERVICE);
                    IWallpaperManager service = IWallpaperManager.Stub.asInterface(b);
                    return new WallpaperManager(service, ctx.get)
                }
            }
        );
    }

    static void registerService(String serviceName, Class<T> serviceClass, ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }
}

获取时

SystemServiceRegistry {
    static String getSystemServiceName(Class<?> serviceClass) {
        return SYSTEM_SERVICE_NAMES.get(serviceClass);
    }
}

WallpaperMS 向ServiceManager注册自己的binder

class WallpaperManagerService {
    static class Lifecycle {
        onStart() {
            Class klass = Class.forName("com.android.server.wallpaper.WallpaperManagerService");
            mService = klass.getConstructor(Context.class).newInstance(getContext());//反射创建service
            publishBinderService(Context.WALLPAPER_SERVICE, mService);
        }
    }
}

改壁纸接口

WallpaperManager {
    setBitmap(Bitmap bitmap) {
        setBitmap(bitmap, null, true);
    }

    //最终调到这个。
    //which = FLAG_SYSTEM| FLAG_LOCK,具体是1<<0和 1<<1
    setBitmap(Bitmap fullImage, Rect visibleCropHint,
            boolean allowBackup, @SetWallpaperFlags int which, int userId) {
        

        WallpaperSetCompletion completion = new WallpaperSetCompletion();//如名字,监听壁纸设置完成

        //sGlobal.mService就是WallpapaerManagerService的binder。
        //参数里没有fullImage。这个方法只是返回了fd
        ParcelFileDescriptor fd = sGlobal.mService.setWallpaper(null, ..., completion, userId);
         
        if (fd != null) {
            FileOutputStream fos = null;
            fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);//打开输出流
            fullImage.compress(.., fos); //把图片保存到输出流里
            fos.close();
            completion.waitForCompletion(); //等30ms,设置成功的话,能接收到回调。
        }
    }
}

进到wallpaperMS里

WallpaperMS {
    setWallpaper(String name, ..., int which, ., int userId) { //name=null
        ...

        WallpaperData wallpaper;
        wallpaper = getWallpaperSafeLocked(userId, which);// 获取wallpaperData

        //生成 /data/.../wallpaper 的文件描述符,回传给wallpaperManager
        ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
        ...
        return pfd;
    }
}

获取WallpaperData

WallpaperMS {
    WallpaperData getWallpaperSafeLocked(int userId, int which) {
        SparseArray<WallpaperData> whichSet = (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
        WallpaperData wallpaper = whichSet.get(userId);

        //如果wallpaper是null,重新load一次,如果load后还是获取不到,新建wallpaperData并保存
        ...

        return wallpaper;
    }
}

wallpaperMS生成文件描述符,用于返回给wallpaperManager

WallpaperMS {
    ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
            Bundle extras) {
        ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile, MODE_CREATE | MODE_READ_WRITE | MODE_TRUNCATE); // 创建/data/../wallpaper文件的描述符
        
        wallpaper.wallpaperId = makeWallpaperIdLocked();// id + 1
        return fd;
    }
}

WallpaperManager监听壁纸设置完成

WallpaperManager {
    //这个IWallpaperManagerCallback.aidl中,原生里只有一个借口:onWallpaperChanged()
    class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub {
        CountDownLatch mLatch;

        void waitForCompletion() {
            mLatch.await(30, TimeUnit.SECONDS);//本线程park,30s超时
        }

        //完成的话,能接收到WallpaperMS的回调
        @Override
        void onWallpaperChanged() {
            mLatch.countDown(); //设置完成时,由binder线程回调,unpark本线程
        }
    }
}

CountDownLatch的原理

使用aqs实现的,为了保证线程同步。

1,调用CountDownLetch.await(long timeout, TimeUnit unit)时,获取int state,想要的state是0,但此时是1。
所以生成一个Node,保存当前的Thread。并park当前thread。

2,其他线程调用CountDownLetch的countDown时,compareAndSetState(1, 0),把state设置为0。并从Node链表中取出距离head最近的node,获取node中保存的thread,并unpark.

WallpaperMS发送壁纸设置完成的消息

系统启动到third_party apps can start阶段,会调用switch(UserHandle.USER_SYSTEM, null)。
然后创建wallpaperData.wallpaperObserver,并启动监听

WallpaperMS {
    switch(int userId, IRemoteCallback reply) {
        
        WallpaperData systemWallpaper;
        ...

        systemWallpaper = getWllpaperSafeLocked(userId, FLAG_SYSTEM);
        
        // 创建observer,并启动监听
        if (systemWallpaper.wallpaperObserver == null) {
            systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
            systemWallpaper.wallpaperObserver.startWatching();
        }
    }
}

如何监听的?

WallpaperMS {
    class WallpaperObserver extends FileObserver {

        //监听/data/../0/这个目录下所有文件
        WallpaperObserver(WallpaperData wallpaper) {
            super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
                    CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
            ...
        }

        super.startWatching() {
            
        }
    }
}

加载wallpaperData.

时机:系统AMS ready时,通过SystemServiceManager告诉各个SystemService,接口是onBootPhase(int)。

WallpaperMS {
    loadSettingsLocked(int userId, boolean keepDimensionHints) {
        ...

        WallpaperData wallpaper = mWallpaperMap.get(userId);
        if (wallpaper == null) {
            wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
            mWallpaperMap.put(userId, wallpaper); //创建个新的data,保存到map里

            if (!wawllpaper.cropExists()) {
                if (wallpaper.sourceExist()) {
                    //如果/data/system/users/0/中,只有wallpaper_orig文件,没有wallpaper文件,则生成
                    generateCrop(wallpaper);
                }
            }
        }

        //解析/data/system/users/0/wallpaper_info.xml文件
        //解析到mWallpaperMap的wallpaperData里,component是第三发软件。
        //解析到mDisplayDatas的DisplayData里

        保证wallpaperData和displayData中的显示区域,至少是Display的长边长度
    }
}

system*service*等类

abstrat class SystemService {
    public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100;
    ...
    public static final int PHASE_BOOT_COMPLETED = 1000;

    void onBootPhase(int phase) {}
}

ServiceManager 通过jni注册binder

SystemServer 使用SystemServiceManager启动各个SystemService

SystemServiceManager 用于管理各个SystemService,创建它们、启动它们、保存它们、通知它们的各个状态

SystemService 对应了各个服务(ams、pms..),抽象出了几个接口(onBootPhase\ onStart\ onUserStart\ onUserSwitch\ onUnlockUser...)这些状态被SystemServiceManager回调。

SystemServiceRegistry 是app端的缓存,保存了name 和 各种serviceManager,serviceManager里持有service的binder

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值