设置壁纸
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