前言
SystemUI是系统启动中第一个用户肉眼可见的应用,系统为用户提供的系统级别的信息显示与交互的一套UI组件,其功能包罗万象,比如开机后看到的锁屏界面,充电时充电界面,状态栏,导航栏,多任务栏等,都是与Android手机用户息息相关的功能。
SystemUI概览
- SystemUI属于系统级的apk,位置在frameworks\base\packages\SystemUI,主要功能有:
- StatusBar:通知消息提示和状态展现
- NavigationBar:返回,HOME,Recent
- KeyGuard:锁屏模块可以看做单独的应用,提供基本的手机个人隐私保护
- Recents:近期应用管理,以堆叠栈的形式展现。
- Notification Panel:展示系统或应用通知内容。提供快速系统设置开关。
- VolumeUI:来用展示或控制音量的变化:媒体音量、铃声音量与闹钟音量
- 截屏界面:长按电源键+音量下键后截屏,用以展示截取的屏幕照片/内容
- PowerUI:主要处理和Power相关的事件,比如省电模式切换、电池电量变化和开关屏事件等。
- RingtonePlayer:铃声播放
- StackDivider:控制管理分屏
- PipUI:提供对于画中画模式的管理
尽管从表现形式上看,SystemUI和普通的Android APP有较大的差别,但其本质和普通APP并没有什么差别,也是以apk的形式存在,也是通过Android的4大组件中的Activity、Service、BroadcastReceiver来接受外界的请求并执行相关的操作,只不过它们所接受的请求主要来自各个系统服务而已。不同于一般的 app,它不可卸载也不可以被第三方应用替换。
SystemUI APK路径:
/system/priv-app/SystemUI/
SystemUI的启动流程
先找到 framework/base/service/java/com/android/server/SystemServer.java 文件,里面有个main()方法,main 方法如下:
public static void main(String[] args){
new SystemServer().run()
}
main 方法里启动了 run() 方法,而在 run 方法中调用了 startBootstrapServices()
方法和 startOtherServices()
方法,在 startOtherServices()
里 mActivityManagerService.systemReady
创建线程去执行startSystemUi(context)
,这里将启动 SystemUI。具体方法如下:
static final void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
然后我们进入设置启动 systemui 程序的 SystemUIService
文件里,该文件在framework/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java.我们看该文件的onCreate()
方法。方法如下:
37 public void onCreate() {
38 super.onCreate();
39 ((SystemUIApplication) getApplication()).startServicesIfNeeded();
40
41 // For debugging RescueParty
42 if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
43 throw new RuntimeException();
44 }
45
46 if (Build.IS_DEBUGGABLE) {
47 // b/71353150 - looking for leaked binder proxies
48 BinderInternal.nSetBinderProxyCountEnabled(true);
49 BinderInternal.nSetBinderProxyCountWatermarks(1000,900);
50 BinderInternal.setBinderProxyCountCallback(
51 new BinderInternal.BinderProxyLimitListener() {
52 @Override
53 public void onLimitReached(int uid) {
54 Slog.w(SystemUIApplication.TAG,
55 "uid " + uid + " sent too many Binder proxies to uid "
56 + Process.myUid());
57 }
58 }, Dependency.get(Dependency.MAIN_HANDLER));
59 }
60 }
可以看到有一句((SystemUIApplication) getApplication()).startServicesIfNeeded()
,这句很关键,我们再进入 startServicesIfNeeded()
,看看具体是如何启动系统服务的。该方法如下:
144 private void startServicesIfNeeded(String[] services) {
145 if (mServicesStarted) {
146 return;
147 }
148 mServices = new SystemUI[services.length];
149
150 if (!mBootCompleted) {
151 // check to see if maybe it was already completed long before we began
152 // see ActivityManagerService.finishBooting()
153 if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
154 mBootCompleted = true;
155 if (DEBUG) Log.</