设置壁纸
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());//反射创建servicepublishBinderService(Context.WALLPAPER_SERVICE, mService);}}
}
改壁纸接口
WallpaperManager {setBitmap(Bitmap bitmap) {setBitmap(bitmap, null, true);}//最终调到这个。//which = FLAG_SYSTEM| FLAG_LOCK,具体是1<<0和 1<<1setBitmap(Bitmap fullImage, Rect visibleCropHint,boolean allowBackup, @SetWallpaperFlags int which, int userId) {WallpaperSetCompletion completion = new WallpaperSetCompletion();//如名字,监听壁纸设置完成//sGlobal.mService就是WallpapaerManagerService的binder。//参数里没有fullImage。这个方法只是返回了fdParcelFileDescriptor 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 的文件描述符,回传给wallpaperManagerParcelFileDescriptor 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 + 1return fd;}
}
WallpaperManager监听壁纸设置完成
WallpaperManager {//这个IWallpaperManagerCallback.aidl中,原生里只有一个借口:onWallpaperChanged()class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub {CountDownLatch mLatch;void waitForCompletion() {mLatch.await(30, TimeUnit.SECONDS);//本线程park,30s超时}//完成的话,能接收到WallpaperMS的回调@Overridevoid 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