设置壁纸
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的长边长度
}
}
systemservice等类
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
# 壁纸文件变化的监听
wms 初始化时,调用switchUser()创建WallpaperObserver,用于监听壁纸目录下文件的变化。
class WMS {
void switchUser(..) {
if (systemWallpaper.wallpaperObserver == null) {
systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
systemWallpaper.wallpaperObserver.startWatching();
}
}
}
监听的是壁纸目录里的文件
class WallpaperMS {
class WallpaperObserver extends FileObserver {
WallpaperObserver(WallpaperData wallpaper) {
super(getWallpaperDir(wallpaper.userId).getAbsolutePath(), .);//监听目录保存到mFiles里
}
}
}
FileObserver监听文件变化
class FileObserver {
//启动监听线程
static {
s_observerThread = new ObserverThread();
s_observerThread.start();
}
List<File> mFiles; //保存要监听的文件
//开始监听指定的文件
void startWatch() {
mDescriptors = s_observerThread.startWatching(mFiles, mMask, this); //一个进程里,只有一个s_observerThread
}
static class ObserverThread extends Thread {
int m_fd; //调用native int init()方法获取的,是inotify实例的fd,inotify是kernal层实现监听文件变化的方式。
void run() {
observe(m_fd); //native方法,android_util_FileObserver.cpp里,开始阻塞监听inofity的变化。
}
//开始监听指定文件
int[] startWatching(List<File> files, ., FileObserver observer) {
String[] paths; //把files转成路径
int[] wfds = new int[count]; //类似于要监听文件的id
startWatching(m_fd, paths, ., wfds); //native方法,传入要监听的文件路径给inotify。如果要监听的文件有变,则inotify会有消息。上面的observer就读取到变化,最后通过native方法onEvent()回调回来
m_observers.put(wfd, observer);
return wfds;
}
//文件变化->inotify变化->observer监听阻塞被唤醒 ->调到这
onEvent(...) {
从m_observers里取出observer来,回调
}
}
}
WMS里接收到文件变化
WMS {
class WallpaperObserver {
onEvent(int event, String path) {
if (sysWallpaperChanged || lockWallpaperChanged) {//根据path,判断是哪个壁纸文件变化了
...
if (wallpaper.wallpaperComponent == null //壁纸软件的componentName
|| event != FileObserver.CLOSE_WRITE
|| wallpaper.imageWallpaperPending) {
...
if (written) { //文件写完并close了,或者有文件被移动到被监听目录
...
if (wallpaper.setComplete != null) {
wallpaper.setComplete.onWallpaperChanged(); //这个就是wallpaperManager传过来的binder。
}
}
}
}
}
}
}
wm中,setBitmap来设置壁纸
WMS中,setWallpaper来获取要修改壁纸的fd
WMS {
//没有直接修改文件,而是返回了要修改壁纸的 文件描述符
ParcelFileDescriptor setWallpaper(String name, ..., int which, IWallpaperManagerCallback completion, int userId) {
...
wallpaper = getWallpaperSafeLocked(userId, which);
ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras); //生成fd
wallpaper.setComplete = completion;
return pfd;
}
}
获取要修改壁纸的文件描述符
WMS {
ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper, Bundle extras) {
...
ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE); //本质是根据path和mode,生成fd
...
return fd;
}
}
SystemUi端怎么知道壁纸改变了?
XxImageWallpaper {
}
壁纸怎么显示出来的?
wms接收到系统启动的phase third party apps can start 阶段,执行switchUser。
其中,不仅创建wallpaperObserver监听文件夹变化。
还执行switchWallpaper(systemWallpaper, reply)来连接wallpaperService
WMS {
switchUser(int userId, .) {
systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
...
switchWallpaper(systemWallpaper, reply);
}
}
计算要绑定哪个service。默认是systemUI的ImageWallpaper,如果设置为了第三方app当做壁纸,则会修改这个component。
WMS {
switchWallpaper(WallpaperDzta wallpaper, .) {
//wallpaper.nextWallpaperComponent 在WMS启动时,loadSettingsLock中,被赋值为mImageWallpaper,是写在xml中的,内容是systemUI的那个ImageWallpaper
ComponentName cname = 先取wallpaper.wallpaperComponent;如果是null,则取wallpaper.nextWallpaperComponent;
if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, .)) { //取bind service
}
}
}
绑定wallpaperData中的wallpaperComponent指向的service
WMS {
boolean bindWallpaperComponentLocked(ComponentName componentName, ...) {
ServiceInfo si = mIPackageManager.getServiceInfo(componentName, ..); //获取ImageService的信息。
WallpaperInfo wi = null;
if (component != null && !component.equals(mImageWallpaper)) {//如果不是systemUI的那个ImageService
...
}
int componentUid = MIPackageManager.getPackageUid(componentName.getPackageName(), ., wallpaper.userId);
//用systemUI.imageService时,wi是null。
//componentUid 是app的uid
WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper, componentUid);
//intent.mAction="android.service.wallpaper.WallpaperService"
//intent.mComponent=componentName,imageService所在的componentName
if (!mContext.bindServiceAsUser(intent, newConn, ..)) {
}
...
if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null
&& !wallpaper.equals(mFallbackWallpaper)) {
detachWallpaperLocked(mLastWallpaper);//会执行 mContext.unbindService(wallpaper.connection)
}
...
}
}
systemUI的ImageService被启动,返回IBinder。
XxImageWallpaper extends ImageWallpaper extends WallpaperService {
IBinder onBind(Intent intent) {
return new IWallpaperServiceWrapper(this); // 2个binder接口,attach\ detach
}
}
链接ImageService的类。
WMS {
class WallpaperConnection extends IWallpaperConnection.Stub implements ServiceConnection {
onServiceConnected(ComponentName name, IBinder service) {
if (mWallpaper.connection == this) {
mService = IWallpaperService.Stub.asInterface(service); //获得ImageService端的binder
attachServiceLocked(this, mWallpaper); //执行 DisplayConnector的connectLocked(),connector一般就是defaultDisplayId一个。
//还会保存WallpaperData到文件里。
...
}
}
}
}
交给DisplayConnector来连接
WMS {
class WallpaperConnection {
class DisplayConnector {
connectLocked(WallpaperConnection connection, WallpaperData wallpaper) {
connection.mService.attach(connection, mToken, ...); //把connection回传给systemUI.imageService
}
}
}
}
systemUI.imageService接收到binder回调。
WallpaperService extends Service {
class IWallpaperServiceWrapper extends IWallpaperService.Stub { //这个binder被传给wms,wms回调attach方法
attach(IWallpaperConnection conn, ...) {
mEngineWrapper = new IWallpaperEngineWrapper(., conn, ...);
}
}
}
systemUI的IWallpaperEngineWrapper 来处理conn。把自己(IWallpaperEngineWrapper)传给conn
WallpaperService {
class IWallpaperEngineWrapper extends IWallpaperEngine.Stub {
IWallpaperEngineWrapper(WallpaperService context, IWallpaperConnection conn, ...) {
mConnection = conn;
...
//发给SystemUI的主线程来处理
Message msg = mCaller.obtainMessage(DO_ATTACH);
mCaller.sendMessage(msg);
}
//做了个封装,这里处理
void executeMessage(Message m) {
case DO_ATTACH: {
mConnection.attachEngine(this, mDisplayId); //把自己(IWallpaperEngineWrapper)传给conn
Engien engine = onCreateEngine(); //创建Engine
mEngine = engine;
engine.attach(this); //*这里应该是绘制壁纸的地方*
}
}
}
}
总结一下,WMS和WallpaperService之间相互持有的关系
-
WMS启动WallpaperService后,
WMS.WallpaperConnection.mService = WallpaperService.IWallpaperServiceWrapper extends IWallpaperService.Stub -
WMS.WallpaperConnection.mService调用IWallpaperService的attach接口,将WMS.WallpaperConnection传给WallpaperService。
WallpaperService.IWallpaperEngineWrapper.mConnection = WMS.WallpaperConnection extends IWallpaperConnection.Stub -
WallpaperService.IWallpaperEngineWrapper.mConnection 调用attachEngine()接口,将WallpaperService.IWallpaperEngineWrapper传给WMS
WMS.WallpaperConnection.DisplayConnector.mEngine = WallpaperService.IWallpaperEngineWrapper extends IWallpaperEngine.Stub
engine绘制壁纸
WallpaperService{
class Engine {
void attach(IWallpaperEngineWrapper wrapper) {
mConnection = wrapper.mConnection;
mSession = WindowManagerGlobal.getWindowSession(); //mSession是通过WindowMS获取的Session,用来跟WindowMS通信
mWindow.setSession(mSession); //mWindow是本类里创建的,是IWindow.Stub 的子类,用于WindowMS告诉app端windowFocusChanged等信息
onCreate(mSurfaceHolder); //自己的状态回调函数,ImageWallpaper.GLEngine里有具体实现。用于创建ImageWallpaperRenderer。
updateSurface(false, false, false);
}
}
}
#创建surface, WallpaperService获取到WindowMS创建的Surface
WallpaperService {
class Engine {
void updateSurface(...) {
if (...|| creating || ...) {
try {
if (!mCreated) {
if (mSession.addToDisplay(mWindow, ..., mInputChannel, .) < 0) {
//<0 表示添加失败
return;
}
mCreated = true;
}
int relayoutResult = mSession.relayout(mWindow, ..., mSurfaceControl, .);
if (mSurfaceControl.isValid()) {
mSurfaceHolder.mSurface.copyFrom(mSurfaceControl); //surfaceControl里持有surface的long mNativeObject。这里是把SurfaceControl.mNativeObject传给Surface
mSurfaceControl.release();
}
if (!mSurfaceHolder.mSurface.isValid()) {//检查一遍,surface不可用就return
return;
}
try {
if (surfaceCreating) {
onSurfaceCreated(mSurfaceHolder); //子类ImageWallpaper里的GLEngine会有这个方法的实际实现。
}
}
}
}
}
}
}
ImageWallpaper.GLEngine extends WallpaperService.Engine 中,使用ImageWallpaperRenderer来显示壁纸
ImageWallpaper {
class GLEngine {
GLWallpaperRenderer mRenderer;
onSurfaceCreated(SurfaceHolder holder) {
mWorker.getThreadHandler() //mWorker就是个HandlerThread。异步线程
.post(
() -> {
mEglHelper.init(holder); //holder里保存了surface,使用这个surface,创建EGLSurface并保存到EglHelper里
mRenderer.onSurfaceCreated(); //mRenderer是ImageWallpaperRenderer,在onCreate里就创建了。
}
)
}
}
}
ImageWallpaperRenderer implements GLWallpaperRenderer {
void onSurfaceCreated() {
if (!loadBitmap()) { //加载
} else {
}
mWallpaper.setup(mBitmap); //把壁纸bitmap,保存到ImageGLWallpaper mWallpaper中。是以int mTextureId来保存的地址
}
}
从WallpaperManager中,取壁纸
ImageWallpaperRenderer {
boolean loadBitmap() {
if (mWallpaperManager != null && mBitmpa == null) {
mBitmpa = mWallpaperManager.getBitmap(); //从WallpaperManager中取
}
...
return mBitmap;
}
}
renderer 持有bitmap,可以画壁纸
mEglHelper 持有surface。
这2者之间,有个共同的参数 EGL14.EGL_DEFAULT_DISPLAY = 0;通过这个参数,可以获取同一个EGLDisplay。
WMS通过IWindow,用接口resized,触发draw行为。最后到Engine.drawFrame()
ImageWallpaper {
class GLEngine {
requestRendererInternal() {
if (readyToRender) {
//从这2个代码看。是render把bitmap绘制到buffer里,eglHelper把buffer交给SurfaceFlinger去画出来
mRenderer.onDrawFrame();
if (!mEglHelper.swapBuffer());
}
}
}
}