SystemUI属于android系统级的apk,位置在frameworks\base\packages\SystemUI,主要功能有:
1)状态栏信息显示,比如电池,wifi信号,3G/4G等icon显示
2)通知面板,比如系统消息,第三方应用消息,都是在通知面板显示。
3)近期任务栏显示面板,比如长按主页或近期任务快捷键,可以显示近期使用的应用。
4)提供截图服务,比如电源+音量加可以截图。
5)提供壁纸服务,比如壁纸的显示。
6)提供屏保服务。
7)系统UI显示,比如系统事件到来时,显示系统UI提示用户。
首先看一下SystemUI的代码结构,如下图:
一个一个文件介绍,首先docs里面是用markdown编写的一个说明文档demo_mode.md,有兴趣的同学可以打开看一下(全英文),res、src和tests文件不多说了,Android.mk文件里的内容,下面会重点讲解。
首先先放一段android.mk的代码
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := SystemUI-proto-tags
LOCAL_SRC_FILES := $(call all-proto-files-under,src) \
src/com/android/systemui/EventLogTags.logtags
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
include $(BUILD_STATIC_JAVA_LIBRARY)
# ------------------
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := \
Keyguard \
android-support-v7-recyclerview \
android-support-v7-preference \
android-support-v7-appcompat \
android-support-v14-preference \
android-support-v17-leanback \
framework-protos \
SystemUI-proto-tags
LOCAL_JAVA_LIBRARIES := telephony-common telephony-ext
LOCAL_PACKAGE_NAME := SystemUI
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_RESOURCE_DIR := \
frameworks/base/packages/Keyguard/res \
$(LOCAL_PATH)/res \
frameworks/support/v7/preference/res \
frameworks/support/v14/preference/res \
frameworks/support/v7/appcompat/res \
frameworks/support/v7/recyclerview/res \
frameworks/support/v17/leanback/res
LOCAL_AAPT_FLAGS := --auto-add-overlay \
--extra-packages com.android.keyguard:android.support.v7.recyclerview:android.support.v7.preference:android.support.v14.preference:android.support.v7.appcompat \
--extra-packages android.support.v17.leanback
ifneq ($(SYSTEM_UI_INCREMENTAL_BUILDS),)
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_JACK_ENABLED := incremental
endif
include frameworks/base/packages/SettingsLib/common.mk
include $(BUILD_PACKAGE)
ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
include $(call all-makefiles-under,$(LOCAL_PATH))
endif
分析
1、LOCAL_PATH := $(call my-dir)
,一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数‘my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。
2、include $( CLEAR_VARS)
,CLEAR_VARS由编译系统提供((可以在 android 安装目录下的/build/core/config.mk 文件看到其定义,为 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk)),指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等…),除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。
3、LOCAL_MODULE := SystemUI-proto-tags
,LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的。
4、LOCAL_SRC_FILES := xxx
,LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。注意,你不用在这里列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。
5、LOCAL_MODULE_TAGS := optional
模块标记,一般的取值范围为debug、eng、test、optional,如果不定义则默认为optional。对这几个模式的解释为:user:指该模块只在user版本下才编译;eng:指该模块只在eng版本下才编译;tests:指该模块只在tests版本下才编译;optional:指该模块在所有版本下都编译。
6、LOCAL_STATIC_JAVA_LIBRARIES
LOCAL_JAVA_LIBRARIES
使用到的库。
7、LOCAL_PACKAGE_NAME := SystemUI
应用编译后的名称:SysemUI。
8、LOCAL_PRIVILEGED_MODULE := true
不添加此属性,则默认为false,编译后的路径为/system/app/SystemUI,添加了true,则编译后的路径为/system/pri-app/SystemUI,在同样具有系统权限情况下,/system/pri-app下的apk权限比/system/app下大。
这里主要是对于AndroidManifest.xml谈以下几点。
1、android:sharedUserId="android.uid.systemui"
说明是系统级别的apk
2、android:allowBackup
是否允许备份,如果设置为true,则容许任何一个能够打开USB 调试开关的人从Android手机中复制应用数据到外设,一旦应用数据被备份之后,所有应用数据都可被用户读取,当一个应用数据被备份之后,用户即可在其他Android手机或模拟器上安装同一个应用,以及通过恢复该备份的应用数据到该设备上,在该设备上打开该应用即可恢复到被备份的应用程序的状态。所以出于安全考虑,一般都是false。
3、android:supportsRtl="true"
声明你的application是否愿意支持从右到左(原来RTL就是right-to-left 的缩写…)的布局。因为在设置里面,有个开发者选项,里面有个强制使用从右到左的布局方向,如果supportsRtl设置为true,并且点击了这个选项,则会出现如下效果。
如果设置为false,则不会。
4、android:exported="true"
这个属性用于指示该服务是否能够被其他应用程序组件调用或跟它交互。如果设置为true,则能够被调用或交互,否则不能。设置为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。
5、android:persistent="true"
persistent一词的意思是“持久”,将persistent属性设为true,说明这个应用是永久性应用。简单地说,这种应用会顽固地运行于系统之中,从系统一启动,一直到系统关机。并且当异常崩溃时会自动重启。
这里我再稍微啰嗦下,
其实, 在系统启动之时,ActivityManagerService.java的systemReady()会加载所有persistent为true的应用。
可以看到,一开始先加载所有带persistent的app,并且如果这些app的packageName不等于android的话,就执行addAppLock,
addAppLocked()还会检查App进程是否已经启动好了,如果尚未开始启动,此时就会调用startProcessLocked()启动这个进程。所以persistent的app都是系统启动刚开始就启动起来的。
本文主要通过Android.mk和AndroidManifest.xml来介绍下SystemUI的一些特性,
下一篇将会讲解SystemUI的启动流程。
ps:最近几年一直都是在做app的研发工作,现在又干回老本行了,系统级别的代码还得慢慢熟悉,可能讲的比较肤浅,讲的不好的地方欢迎大家指出。