Android4.4 Systemui状态栏状态图标更新流程分析

该篇博文需要一定的Systemui的状态栏基础才能看懂,所以如果各位看官是第一次学习Systemui的状态栏的话建议您点击以下传送门
http://blog.csdn.net/yihongyuelan?viewmode=contents
以下是正文:

状态栏状态图标statusIcons包括:比如像蓝牙、闹钟、耳机插入等等;

statusIcons的布局在android/frameworks/base/packages/SystemUI/res/layout/status_bar.xml

----省略上部分-----
<LinearLayout android:id="@+id/statusIcons"
                              android:layout_width="wrap_content"
                              android:layout_height="match_parent"
                              android:gravity="center_vertical|right"
                              android:orientation="horizontal"
                              android:padding="0dp"
                />
 ----省略下部分---------

在android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
文件中查看start()方法,因为start()是systemui初始化状态栏初始化的入口

public void start() {
       --------------------
        //状态栏aidl实例化
        mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

     ---------------------
      
        // Connect in to the status bar manager service
        StatusBarIconList iconList = new StatusBarIconList();
        //app通知图标的对象
        ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>();
        //状态栏图标的对象
        ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>();
        //状态栏回调方法,这里到时候具体分析
        mCommandQueue = new CommandQueue(this, iconList);

        int[] switches = new int[7];
        ArrayList<IBinder> binders = new ArrayList<IBinder>();
        try {
            mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
                    switches, binders);
        } catch (RemoteException ex) {
            // If the system process isn't there we're doomed anyway.
        }
        ------------------
        //在这里添加添加初始化状态栏图标,比如蓝牙
        // Set up the initial icon state
        int N = iconList.size();
        int viewIndex = 0;
        for (int i=0; i<N; i++) {
            StatusBarIcon icon = iconList.getIcon(i);
            if (icon != null) {
            //将状态栏图标更新到状态栏上
                addIcon(iconList.getSlot(i), i, viewIndex, icon);
                viewIndex++;
            }
        }
    }

上面的代码大概完成这几件事,首先,实例化IStatusBarService.aidl获取对象mBarService,然后实例化回调CommandQueue.java获取对象mCommandQueue,然后mBarServices注册回调mCommandQueue.然后添加初始化状态栏图标(就是手机开机的时候才有初始化)到状态栏上去.

下面具体分析一下:

 //添加一个回调,this是说在该类实现该interface的方法
 mCommandQueue = new CommandQueue(this, iconList);

所以类android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java应该有implements化CommandQueue

public abstract class BaseStatusBar extends SystemUI implements
        CommandQueue.Callbacks{
//由于该类是抽象类,所以接口CommandQueue.Callbacks在他的子类实现
-----------------
}

由于BaseStatusBar.java的子类是一个很复杂的类,所以我们先从简单的类CommandQueue.java分析

在android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
先观察类头结构

//很明显该类是IStatusBar.aidl的子类
public class CommandQueue extends IStatusBar.Stub {

我们继续分析/android/frameworks/base/core/java/com/android/internal/statusbar/IStatusBar.aidl

/** @hide */
oneway interface IStatusBar
{
    //添加状态栏状态图标
    void setIcon(int index, in StatusBarIcon icon);
    //删除状态栏状态图标
    void removeIcon(int index);
    //下面的就不在本次的流程分析中了哈,
    ............
}

所以IStatusbar.aidl主要实现两件事,提供添加和删除状态栏图标接口

继续分析android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java


public class CommandQueue extends IStatusBar.Stub {

    private StatusBarIconList mList;
    private Callbacks mCallbacks;
    private Handler mHandler = new H();

    private class NotificationQueueEntry {
        IBinder key;
        StatusBarNotification notification;
    }

    /**
     * These methods are called back on the main thread.
     */
    public interface Callbacks {
    //添加状态栏状态图标接口
        public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon);
        public void updateIcon(String slot, int index, int viewIndex,
                StatusBarIcon old, StatusBarIcon icon);
        public void removeIcon(String slot, int index, int viewIndex);

        ................
    }
  
    public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
        mCallbacks = callbacks;
        mList = list;
    }
//该方法是IStatusbar.aidl的实现方法,所以当有新的状态图标时,此方法被调用
//具体是被IStatusBarService.aidl中的setIcon(....);
    public void setIcon(int index, StatusBarIcon icon) {
        synchronized (mList) {
        //发送消息给Handler,具体的实现在Handler上,下面有
            int what = MSG_ICON | index;
            mHandler.removeMessages(what);
            mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget();
        }
    }
//该方法是IStatusbar.aidl的实现方法,所以当有状态图标被删除时,此方法被调用
    public void removeIcon(int index) {
        synchronized (mList) {
            int what = MSG_ICON | index;
            mHandler.removeMessages(what);
            mHandler.obtainMessage(what, OP_REMOVE_ICON, 0, null).sendToTarget();
        }
    }

    .................

    private final class H extends Handler {
        public void handleMessage(Message msg) {
            final int what = msg.what & MSG_MASK;
            switch (what) {
                case MSG_ICON: {
                    final int index = msg.what & INDEX_MASK;
                    final int viewIndex = mList.getViewIndex(index);
                    switch (msg.arg1) {
                        case OP_SET_ICON: {
                        //添加状态栏图标执行
                            StatusBarIcon icon = (StatusBarIcon)msg.obj;
                            StatusBarIcon old = mList.getIcon(index);
                            if (old == null) {
                                mList.setIcon(index, icon);
                                //调用PhoneStatusbar.java中的addIcon(...)
                                mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon);
                            } else {
                                mList.setIcon(index, icon);
                                mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,
                                        old, icon);
                            }
                            break;
                        }
                        case OP_REMOVE_ICON:
                        //删除状态栏图标执行
                            if (mList.getIcon(index) != null) {
                                mList.removeIcon(index);
                                mCallbacks.removeIcon(mList.getSlot(index), index, viewIndex);
                            }
                            break;
                    }
                    break;
                }
            }
        }
    }
}

以上我们可以分析得出CommandQueue在状态栏图标主要是实现IStatusbar.aidl,然后在具体的方法中实现,传送消息Handler,在handler里面调用interface中的方法.
这个坑就可以暂时填了,接着下一个坑

//获取IStatusBarService.aidl实例
mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

 ......................
//注册回调 
                 mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
                    switches, binders);

所以,我们接着分析android/frameworks/base/core/java/com/android/internal/statusbar/IStatusBarService.aidl

interface IStatusBarService
{
    void disable(int what, IBinder token, String pkg);
    //调用IStatusbar.aidl的setIcon()方法
    void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription);
    void removeIcon(String slot);

    // ---- Methods below are for use by the status bar policy services ----
    // You need the STATUS_BAR_SERVICE permission
    void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList,
            out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications,
            out int[] switches, out List<IBinder> binders); 
}

该aidl的主要是完成调用IStatusbar.aidl中的setIcon(….)方法和removeIcon(……)方法,并且关联起来IStatusBar.aidl.该aidl的具体实现类是在base/services/java/com/android/server/StatusBarManagerService.java
,这里就不展开继续讨论了,有兴趣的同学可以自己去读一下StatusBarManagerService.java源码.

现在分析android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
.....
}

但是由于BaseStatusBar中implements 了 CommandQueue.Callbacks接口

public abstract class BaseStatusBar extends SystemUI implements
        CommandQueue.Callbacks{
.......
}

所以PhoneStatusBar肯定必须实现CommandQueue.callbacks中的方法
所以PhoneStatusBar.java

public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
..............

 protected PhoneStatusBarView makeStatusBarView() {
.....
mStatusIcons = (LinearLayout) mStatusBarView.findViewById(R.id.statusIcons);
.....
}
//添加状态栏图标
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
        if (SPEW) Log.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
                + " icon=" + icon);
        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
        view.set(icon);
        mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
    }

    public void updateIcon(String slot, int index, int viewIndex,
                           StatusBarIcon old, StatusBarIcon icon) {
        if (SPEW)
            Log.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
                    + " old=" + old + " icon=" + icon);
        StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
        view.set(icon);
    }

    public void removeIcon(String slot, int index, int viewIndex) {
        if (SPEW)
            Log.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
        mStatusIcons.removeViewAt(viewIndex);
    }
............
}

所以总结一下,当我有状态图标更新的时候,首先是IStatusBarService.aidl中的setIcon(….)被调用,然后调用IStatusBar.aidl中的setIcon(……..),确切的说是调用IStatusBar.aidl中的实现类CommandQueue.java中的setIcon(…)方法,然后利用Handler机制发送消息到CommandQueue.java中的内部Handler中,然后调用handler里面调用CommandQueue.Callbacks接口interface中的addIcon(…..)方法,确切的说是调用PhoneStatusBar.java中的addIcon(…..),在PhoneStatusBar.java中的addIcon(…..)方法中,mStatusIcons调用mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));然后状态栏图标就更新到状态栏上了.删除流程也一样,就不详细说了哈

相对之前的信号流程,状态栏流程更加复杂一些.所以大家必须得耐下性子来看,最主要这些流程不仅仅是设计到systemui,还涉及到了其他非systemui的类,所以比较复杂点.欢迎大家多多交流.文笔有限,有错欢迎指出

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值