systemui 分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lf12345678910/article/details/52668332

手机SystemUI

在源码中的位置/frameworks/base/package/SystemUI

SystemUI是什么?

systemui : 截屏操作TakeScreenshotService、图片壁纸ImageWallpaper、低电警告powerui、播放铃声ringtoneplayer、usb、volumeui、状态栏statusbar、导航栏navigationbar、最近使用列表recents、锁屏keyguardviewmediator

状态栏需要实时反馈系统状态,那么它就会长存系统中(AndroidManifest.xml中的android:persistent="true"),而在Android中长存系统运行的组件只有Service,那么,状态栏就是一个长存系统进程空间运行的Service,它是一个系统服务。

运行于一个名为SystemUIService的system_server进程通过Context.startService()方式启动的常规Android服务中,并且通过WindowManager.addView()创建他们的窗口。

1.    SystemUI结构

SystemUIService:一个普通的Android服务,它以一个容器的角色运行于SystemUI进程中。在它内部运行着多个子服务,其中之一便是状态栏与导航栏的实现者——BaseStatusBar的子类之一。

扫描二维码关注公众号,回复: 6022046 查看本文章

IstatusBarService:即系统服务StatusBarManagerService,状态导航栏向外界提供服务的前端端口,运行于system_server进程中。

BaseStatusBar及其子类:状态栏与导航栏的实际实现者,运行于SystemUIService中。

IstatusBar,即SystemUI中的CommandQueue,联系StatusBarManagerService与BaseStatusBar的桥梁。

ImageWallpaper、RecentActivity、TaskScreenshotService等都是标准的Android应用程序组件,且相互独立。

1.    SystemUI启动流程

状态栏和导航栏运行于一个名称为SystemUIService的Service中,因此其启动过程就是SystemUIService的启动过程。

SystemUIService何时由谁启动?作为一个系统级别的UI组件,应是在系统启动过程中完成。在负责启动各种系统服务的ServerThread中,当核心系统服务启动完成后,ServerThread会通过调用ActivityManagerService.systemReady()方法通知AMS系统已经就绪。这个systemReady拥有一个名为goingCallback的Runnable实例作为参数。顾名思义,当AMS完成对systemReady()的处理后将会回调这一Runnable的run()方法。在这一run()方法中可以找到SystemUI的身影。则启动流程如图所示。

PhoneStatusBar,CommandQueue,StatusBarManagerService

当StatusBarManagerService接受到操作状态栏与导航栏的请求时,首先将请求信息保存在副本中,然后再将这一请求通过mBar(即CommandQueue)发送给BaseStatusBar。

StatusBarManagerService作用与工作原理:在ServerThread中创建(参考代码SystemServer.java->main()->run()->startOtherServices())。

①StatusBarManagerService是SystemUI中状态栏与导航栏在system_server的代理。所有对状态栏和导航栏有需求的对象都可以通过获取StatusBarManagerService的实例达到其目的。不过应具备权限。

②它保存了状态栏和导航栏所需信息的副本,用于在SystemUI意外退出之后的恢复。

PhoneStatusBar

PhoneStatusBar通过IstatusBarService来访问StatusBarManagerService;

StatusBarManagerService通过CommandQueue来和PhoneStatusBar交互。

在SystemUiApplication中,根据需要启动以下的Service

privatefinal Class<?>[] SERVICES = new Class[]

 {

com.android.systemui.keyguard.KeyguardViewMediator.class,

com.android.systemui.recent.Recents.class,

com.android.systemui.volume.VolumeUI.class,

com.android.systemui.statusbar.SystemBars.class,

com.android.systemui.usb.StorageNotification.class,

com.android.systemui.power.PowerUI.class,

com.android.systemui.media.RingtonePlayer.class

};

1.   StatusBar Icon 加载

相关类:

PhoneStatusBarPolicy设置图标,通过监听系统状态相关的广播来修改图标

StatusBarManager

StatusBarManagerService

CommandQueue

PhoneStatusBar

BaseStatusBar

系统启动时在SystemServer的main->run()->startOtherServices(),

if (!disableSystemUI) {

try {

Slog.i(TAG, "Status Bar");

statusBar = newStatusBarManagerService(context, wm);

ServiceManager.addService(Context.STATUS_BAR_SERVICE,statusBar);

               } catch (Throwable e) {

reportWtf("startingStatusBarManagerService", e);

               }

            }

而StatusBarManagerService在构造方法中,

publicStatusBarManagerService(Context context,WindowManagerServicewindowManager) {

mContext = context;

mWindowManager = windowManager;

final Resources res = context.getResources();

mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons));

LocalServices.addService(StatusBarManagerInternal.class,mInternalService);

}

<!-- Do not translate. Defines the slots for theright-hand side icons. That is to say,the icons in the status bar that are not notifications. -->

<string-arrayname="config_statusBarIcons">

<item><xliff:gid="id">ime</xliff:g></item>

<item><xliff:gid="id">sync_failing</xliff:g></item>

<item><xliff:gid="id">sync_active</xliff:g></item>

<item><xliff:gid="id">cast</xliff:g></item>

<item><xliff:gid="id">hotspot</xliff:g></item>

<item><xliff:gid="id">location</xliff:g></item>

<item><xliff:gid="id">bluetooth</xliff:g></item>

<item><xliff:gid="id">nfc</xliff:g></item>

<item><xliff:gid="id">tty</xliff:g></item>

<item><xliff:gid="id">speakerphone</xliff:g></item>

<item><xliff:gid="id">zen</xliff:g></item>

<item><xliff:gid="id">mute</xliff:g></item>

<item><xliff:gid="id">volume</xliff:g></item>

<item><xliff:gid="id">wifi</xliff:g></item>

<item><xliff:gid="id">cdma_eri</xliff:g></item>

<item><xliff:gid="id">data_connection</xliff:g></item>

<item><xliff:gid="id">phone_evdo_signal</xliff:g></item>

<item><xliff:gid="id">phone_signal</xliff:g></item>

<item><xliff:gid="id">battery</xliff:g></item>

<item><xliff:gid="id">alarm_clock</xliff:g></item>

<item><xliff:gid="id">secure</xliff:g></item>

<item><xliff:gid="id">clock</xliff:g></item>

<item><xliff:gid="id">sdcard_absent</xliff:g></item>

</string-array>

图标名称和顺序

总结下,在SystemServer进程中,维系了一个StatusBarManagerService对象statusBar,而statusBar对象维系了一个StatusBarIconList对象mIcons,这样就实现了在SystemServer中维系了一个mIcons,而这个mIcons存储了status bar中图标(String)和顺序。

StatusBarManagerService对外接口三个

setIcon

setIconVisibility

removeIcon

当然,这些接口是系统内容使用的,应用只能通过间接的方法去改变系统状态图标,无法直接更改。例如要让系统状态显示设置了闹钟,就需要发送anction.intent.action.ALARM_CHANGED广播,在SystemUi中接收这一广播并调用以上接口来改变图标的显示情况。

UI有2个接口,在CommandQueue中实现

setIcon

removeIcon

经过桥接的CommandQueue最后交给UI实现的接口3个

addIcon如果调用的setIcon的slot没有在SystemUI中的数据有记录,那么会调用这个,SystemUI添加上一个StatuaBarIconView

updateIcon如果调用的setIcon的slot在SystemUI中有记录,调用这个,SystemUI更新下已有的状态

removeIconSystemUI移除一个已经添加的图标

下图为加载Icon的时序图:

最后到StatusBarIconView的set中看更新状态

PS:

setIcon的参数:

slot:用于声明图标的意图。它必须存在于config_statusBarIcons所预定的意图列表中。

Icon:用于显示图标资源id。

iconLevel:图标资源level。

contentDescription:详细描述图标的含义。

猜你喜欢

转载自blog.csdn.net/lf12345678910/article/details/52668332