析壁纸机制分析

文章记录自己的学习过程,供日后参考。

首先要知道壁纸设置的大体流程:上层应用调用wallpaperManager.setStream()或其他接口进行设置壁纸,WallpaperManagerService首先将壁纸copy到/data/system/user/0/目录下,WallpaperManagerService对该目录注册了一个WallpaperObserver,拷贝壁纸成功后会触发调用WallpaperObserver.onEvent()函数,onEvent()函数首先调用notifyCallbacksLocked()触发回调,然后再调用bindWallpaperComponentLocked()做进行进一步的壁纸更换。虽然整个壁纸机制有WallpaperManager、WallpaperService、ImageWallpaper、WallpaperManagerService、Globals、DrawableEngine、WallpaperData、WallpaperConnection等数据结构,感觉挺复杂的,我们应该剥离他的外表,看清他的本质。我们只要搞清了他们之间怎么交互的?交流些什么东西?就搞清楚了整个壁纸机制,说白了只要搞清楚IWallpaperService.aidl、IWallpaperEngine.aidl、IWallpaperConnection.aidl这三个文件就OK了,因为这三个文件是通信的关键所在。

1.IWallpaperService.aidl

oneway interface IWallpaperService {
    void attach(IWallpaperConnection connection,
    		IBinder windowToken, int windowType, boolean isPreview,
    		int reqWidth, int reqHeight);
}

aidl语言专为Binder设计,因此里面的函数可看做是通信接口。

(1).WallpaperService.IWallpaperServiceWrapper extends IWallpaperService.Stub;

(2).WallpaperService.onBind()

    /**
     * Implement to return the implementation of the internal accessibility
     * service interface.  Subclasses should not override.
     */
    @Override
    public final IBinder onBind(Intent intent) {
        return new IWallpaperServiceWrapper(this);
    }

从上面两点可以知道:IWallpaperService的Binder本地端在WallpaperService中;WallpaperService服务将是调用mContext.bindService()启动的;IWallpaperService的代理对象将在ServiceConnection.onServiceConnected()中获取。很容易验证WallPaperManagerService中确实是这么干的。

WallPaperManagerService.bindWallpaperComponentLocked():

    boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
            boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
            ........
            Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
            ........
            WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
            intent.setComponent(componentName);
            intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                    com.android.internal.R.string.wallpaper_binding_label);
            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
                    mContext, 0,
                    Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
                            mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
                    0, null, new UserHandle(serviceUserId)));
            if (!mContext.bindServiceAsUser(intent, newConn,
                    Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI,
                    new UserHandle(serviceUserId))) {
           ..........
            }
   }

文章最开头就说了,每次设置壁纸都会调用bindWallpaperComponentLocked()函数,也就是说每次设置壁纸都会重新new WallpaperConnection,重新调用mContext.bindServiceAsUser()绑定启动WallpaperService,为啥要每次重新bind一次呢?防止systemUI挂掉,无法设置壁纸?不管了,反正记住每次设置壁纸时都会bind一次WallpaperService,并且调用WallpaperConnection.onServiceConnected()函数。onServiceConnected()函数中真的获取了IWallpaperService的Binder代理对象。

        public void onServiceConnected(ComponentName name, IBinder service) {
            synchronized (mLock) {
                if (mWallpaper.connection == this) {
                    mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
                    mService = IWallpaperService.Stub.asInterface(service);
                    attachServiceLocked(this, mWallpaper);
                    // XXX should probably do saveSettingsLocked() later
                    // when we have an engine, but I'm not sure about
                    // locking there and anyway we always need to be able to
                    // recover if there is something wrong.
                    saveSettingsLocked(mWallpaper);
                }
            }
        }

mService = IWallpaperService.Stub.asInterface(service);语句获取了IWallpaperService的Binder代理对象。再看看WallpaperConnection.onServiceConnected()函数中调用WallPaperManagerService.attachServiceLocked()干什么?

    void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
        try {
            conn.mService.attach(conn, conn.mToken,
                    WindowManager.LayoutParams.TYPE_WALLPAPER, false,
                    wallpaper.width, wallpaper.height);
        } catch (RemoteException e) {
            Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
            if (!wallpaper.wallpaperUpdating) {
                bindWallpaperComponentLocked(null, false, false, wallpaper, null);
            }
        }
    }

嗯,跨Binder调用IWallpaperService本地端的attach()。看看attach()做了什么?

        public void attach(IWallpaperConnection conn, IBinder windowToken,
                int windowType, boolean isPreview, int reqWidth, int reqHeight) {
            new IWallpaperEngineWrapper(mTarget, conn, windowToken,
                    windowType, isPreview, reqWidth, reqHeight);
        }

直接new IWallpaperEngineWrapper对象,注意传进来的参数,包含壁纸显示参数。IWallpaperEngineWrapper extends IWallpaperEngine.Stub implements HandlerCaller.Callback,所以又知道了IWallpaperEngine的Binder本地端保存在WallpaperService中,代理端返回给WallPaperManagerService.WallpaperConnection.mEngine变量的呢?这个研究到后边应该自然就知道了。IWallpaperEngineWrapper的构造函数将被调用,在构造函数中会post一个handle消息DO_ATTACH,

            switch (message.what) {
                case DO_ATTACH: {
                    try {
                        mConnection.attachEngine(this);
                    } catch (RemoteException e) {
                        Log.w(TAG, "Wallpaper host disappeared", e);
                        return;
                    }
                    Engine engine = onCreateEngine();
                    mEngine = engine;
                    mActiveEngines.add(engine);
                    engine.attach(this);
                    return;
                }

感觉牵涉的越来越多了,没关系,一个个来分析。

先上班,下班再研究。

时间: 2024-08-06 03:42:27

析壁纸机制分析的相关文章

QT开发(六十三)——QT事件机制分析

QT开发(六十三)--QT事件机制分析 一.事件机制 事件是由系统或者QT平台本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事件则是由系统自动发出,如计时器事件. 事件的出现,使得程序代码不会按照原始的线性顺序执行.线性顺序的程序设计风格不适合处理复杂的用户交互,如用户交互过程中,用户点击"打开文件"将开始执行打开文件的操作,用户点击"保存文件"将开始执

Linux通信之poll机制分析

poll机制分析 韦东山 2009.12.10 所有的系统调用,基于都可以在它的名字前加上"sys_"前缀,这就是它在内核中对应的函数.比如系统调用open.read.write.poll,与之对应的内核函数为:sys_open.sys_read.sys_write.sys_poll. 一.内核框架: 对于系统调用poll或select,它们对应的内核函数都是sys_poll.分析sys_poll,即可理解poll机制. sys_poll函数位于fs/select.c文件中,代码如下:

Nginx处理stale事件机制分析

Nginx为提高效率采用描述符缓冲池(连接池)来处理tcp连接,一个连接对应一个读事件和一个写事件,nginx在启动的时候会创建好所用连接和事件,当事件来的时候不用再创建,然而连接池的使用却存在stale事件的问题,以下将详细分析Nginx是如何处理stale事件的,该问题涉及到epoll.Nginx连接与事件的相关知识. 1      Epoll的实现原理 epoll相关的系统调用有:epoll_create, epoll_ctl和epoll_wait.Linux-2.6.19又引入了可以屏蔽

Linux x86_64 APIC中断路由机制分析

不同CPU体系间的中断控制器工作原理有较大差异,本文是<Linux mips64r2 PCI中断路由机制分析>的姊妹篇,主要分析Broadwell-DE X86_64 APIC中断路由原理.中断配置和处理过程,并尝试回答如下问题: 为什么x86中断路由使用IO-APIC/LAPIC框架,其有什么价值? pin/irq/vector的区别.作用,取值范围和分配机制? x86_64 APIC关键概念 Pin 此处的pin特指APIC的中断输入引脚,与内外部设备的中断输入信号相连.从上图中可以看出,

[转]易语言消息机制分析(消息拦截原理)

标 题: [原创]易语言消息机制分析(消息拦截原理)作 者: 红绡枫叶时 间: 2014-12-17,12:41:44链 接: http://bbs.pediy.com/showthread.php?t=195626 我自己做了个易语言的sig签名,方便分析的时候用.易语言例子是静态编译的.版本 5.11易语言其实是基于mfc的,它依然需要mfc的消息派发机制,只不过,自己当了系统与用户间的代理人.所有的消息都要经它转发而已.我在MFC的消息派发函数_AfxDispatchCmdMsg下断点,总

UVM基础之---------uvm report 机制分析

uvm 中的信息报告机制相对来说比较简单,功能上来说主要分为两部分: 第一通过ID对component的信息报告冗余级别进行控制,针对每个冗余级别进行不同的行为控制.这部分工作主要由uvm_report_hander来实现: 主要涉及到的方法有get_report_verbosity_level(severity, id)/get_report_action(severity,id) == uvm_action'(UVM_NO_ACTION) 第二是对message进行格式化的输出,这部分工作主

Linux内核抢占实现机制分析【转】

Linux内核抢占实现机制分析 转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介绍了内核抢占和用户抢占的概念和区别,接着分析了不可抢占内核的特点及实时系统中实现内核抢占的必要性.然后分析了禁止内核抢占的情况和内核抢占的时机,最后介绍了实现抢占内核所做的改动以及何时需要重新调度. [关键字]内核抢占,用户抢占,中断, 实时性,自旋锁,抢占时机,调度时机,schedule,pree

ffmpeg转码MPEG2-TS的音视频同步机制分析

http://blog.chinaunix.net/uid-26000296-id-3483782.html 一.FFmpeg忽略了adaptation_field()数据FFmpeg忽略了包含PCR值的adaptation_filed数据; 代码(libavformat/mpegts.c)分析如下: /* 解析TS包 */int handle_packet(MpegTSContext *ts, const uint8_t *packet){  ...   pid = AV_RB16(packe

MFC消息响应机制分析

---- 摘要: ---- MFC是Windows下程序设计的最流行的一个类库,但是该类库比较庞杂,尤其是它的消息映射机制,更是涉及到很多低层的东西,我们在这里,对它的整个消息映射机制进行了系统的分析,可以帮助程序开发人员对MFC的消息映射机制有一个比较透彻的了解. ---- 关键词:面向对象 消息映射 MFC 程序设计 一.引言---- VC++的MFC类库实际上是Windows下C++编程的一套最为流行的类库.MFC的框架结构大大方便了程序员的编程工作,但是为了更加有效.灵活的使用MFC编程