我是靠谱客的博主 大胆冰淇淋,这篇文章主要介绍SystemUI模块总结SystemUI模块总结,现在分享给大家,希望可以做个参考。

SystemUI模块总结

1,SystemUI路径

SystemUI被放在

framework/base/packages/apps/SystemUI

在该目录的二级目录src/com/android下可看到SystemUI和Keyguard两个目录

复制代码
1
2
3
SystemUI Keyguard

由此可见如今将锁屏界面也整合在SystemUI中

2,SystemUI所需权限

从清单文件中可以发现 SystemUI需要建立以下开通权限用以监听开机广播,读写内存和访问所有用户存储状态,监听物理硬件,控制AM,WM,屏保,
锁屏,recent事件,wifi的展示,截屏,快捷设置入口等

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Used to read storage for all users --> <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.INJECT_EVENTS" /> <uses-permission android:name="android.permission.DUMP" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" /> <uses-permission android:name="android.permission.STATUS_BAR" /> <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" /> <uses-permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK" /> <uses-permission android:name="android.permission.MANAGE_USERS" /> <uses-permission android:name="android.permission.READ_PROFILE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> 。。。。。。 <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" />

3,SystemUI启动流程

SystemUI启动分为两部分
1)Service部分

代码路径:

复制代码
1
2
framework/base/services/java/com/android/server/SystemServer.java

开机后系统会首先启动SystemServer,SystemServer启动后才会带动其他一系列系统服务的启动,也包括SystemUI的启动

复制代码
1
2
3
4
5
public static void main(String[] args) { new SystemServer().run(); }

在SystemUI的main方法中启用了 SystemServer().run();run方法中主要做了以下操作

复制代码
1
2
3
4
5
traceBeginAndSlog("StartServices"); startBootstrapServices(); startCoreServices(); startOtherServices();

而在run()方法中做了startBootstrapServices(),startCoreServices(),startOtherServices()三个操作
而在startOtherServices()中做了startSystemUi(context, windowManagerF)的方法

复制代码
1
2
3
4
5
6
7
8
traceBeginAndSlog("StartSystemUI"); try { startSystemUi(context, windowManagerF); } catch (Throwable e) { reportWtf("starting System UI", e); } traceEnd();

startSystemUi具体实现如下,用Intent启动了SystemUIService

复制代码
1
2
3
4
5
6
7
8
9
10
11
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(); }
2)SystemUI部分

接下来就走到了SystemUIService中,我们看一下SystemUIService中的onCreat方法

复制代码
1
2
3
4
5
6
7
@Override public void onCreate() { super.onCreate(); ((SystemUIApplication) getApplication()).startServicesIfNeeded(); ...... }

可知在SystemUIService中启动了SystemUIApplication中的startServicesIfNeeded()方法

复制代码
1
2
3
4
public void startServicesIfNeeded() { startServicesIfNeeded(SERVICES); }

其中SERVICES是一组所有用户共用的SystemUI服务,如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private final Class<?>[] SERVICES = new Class[] { Dependency.class, //SystemUI的依赖项 NotificationChannels.class, //展示系统或应用通知内容 CommandQueue.CommandQueueStart.class, //StatusBar的扩展类 KeyguardViewMediator.class, //协调与keyguard相关的请求 Recents.class, //近期应用管理 VolumeUI.class, //来用展示或控制音量的变化:媒体音量、铃声音量与闹钟音量 Divider.class, //控制堆栈的服务 SystemBars.class, //通知栏 StorageNotification.class, //存储设备管理 PowerUI.class, //主要处理和Power相关的事件,比如省电模式切换、电池电量变化和开关屏事件等 RingtonePlayer.class, //铃声播放 KeyboardUI.class, //键盘界面 PipUI.class, //画中画 ShortcutKeyDispatcher.class, //系统组件快捷方式 VendorServices.class, //厂商定制的服务 GarbageMonitor.Service.class, //垃圾监视服务 LatencyTester.class, //debug测试 GlobalActionsComponent.class, //全局控制 RoundedCorners.class, //圆角切割 };

下面看看在SystemUIApplication是如何启动这一系列服务的

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
private void startServicesIfNeeded(Class<?>[] services) { if (mServicesStarted) { return; } if (!mBootCompleted) { // check to see if maybe it was already completed long before we began // see ActivityManagerService.finishBooting() if ("1".equals(SystemProperties.get("sys.boot_completed"))) { mBootCompleted = true; if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent"); } } Log.v(TAG, "Starting SystemUI services for user " + Process.myUserHandle().getIdentifier() + "."); TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming", Trace.TRACE_TAG_APP); log.traceBegin("StartServices"); final int N = services.length; //获取启动服务列表的长度 for (int i = 0; i < N; i++) { Class<?> cl = services[i]; if (DEBUG) Log.d(TAG, "loading: " + cl); log.traceBegin("StartServices" + cl.getSimpleName()); long ti = System.currentTimeMillis(); try { /*通过SystemUI创建相应的单例*/ Object newService = SystemUIFactory.getInstance().createInstance(cl); mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } mServices[i].mContext = this; mServices[i].mComponents = mComponents; if (DEBUG) Log.d(TAG, "running: " + mServices[i]); mServices[i].start(); //依次启动相应的服务 log.traceEnd(); // Warn if initialization of component takes too long ti = System.currentTimeMillis() - ti; if (ti > 1000) { Log.w(TAG, "Initialization of " + cl.getName() + " took " + ti + " ms"); } if (mBootCompleted) { mServices[i].onBootCompleted(); } }

上面的代码的逻辑首先获取SERVICE数组中的class名,然后分别实例化他们,最后调用start接口统一启动,因此,每一个UI元素都必须继承自SystemUI这个抽象类,并且重载其中的start方法。

3,SystemUI主要模块

StatusBar:通知消息提示和状态展现

NavigationBar:返回,HOME,Recent

KeyGuard:锁屏模块可以看做单独的应用,提供基本的手机个人隐私保护

Recents:近期应用管理,以堆叠栈的形式展现。

Notification Panel:展示系统或应用通知内容。提供快速系统设置开关。

VolumeUI:来用展示或控制音量的变化:媒体音量、铃声音量与闹钟音量

截屏界面:长按电源键+音量下键后截屏,用以展示截取的屏幕照片/内容

PowerUI:主要处理和Power相关的事件,比如省电模式切换、电池电量变化和开关屏事件等。

RingtonePlayer:铃声播放

StackDivider:控制管理分屏

PipUI:提供对于画中画模式的管理

SystemBar的启动过程

由上文可知SystemBar存在于SystemUIApplication的services集合中,因此在mServices[i].start()时,SystemBars也同时被启动了
下面看一下SystemBar服务,SystemBar继承SystemUI抽象类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
public class SystemBars extends SystemUI { private static final String TAG = "SystemBars"; private static final boolean DEBUG = false; private static final int WAIT_FOR_BARS_TO_DIE = 500; // in-process fallback implementation, per the product config private SystemUI mStatusBar; @Override public void start() { if (DEBUG) Log.d(TAG, "start"); createStatusBarFromConfig(); }

由此可见在SystemUI的start方法中只执行了一个createStatusBarFromConfig()创建了staturbar,SystemBar只是作了一个中间过程
再来看一下createStatusBarFromConfig()方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void createStatusBarFromConfig() { if (DEBUG) Log.d(TAG, "createStatusBarFromConfig"); final String clsName = mContext.getString(R.string.config_statusBarComponent); if (clsName == null || clsName.length() == 0) { throw andLog("No status bar component configured", null); } Class<?> cls = null; try { cls = mContext.getClassLoader().loadClass(clsName); } catch (Throwable t) { throw andLog("Error loading status bar component: " + clsName, t); } try { mStatusBar = (SystemUI) cls.newInstance(); } catch (Throwable t) { throw andLog("Error creating status bar component: " + clsName, t); } mStatusBar.mContext = mContext; mStatusBar.mComponents = mComponents; mStatusBar.start(); if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName()); }

同样也是调用了statusbar中的start方法,再来看一下statusbar中的start方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override public void start() { ... //这里面进行了StatusBar中各个组件的初始化 mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); ... try { /* 经过一系列对象的创建与初始化后,开始向StatusBarService进行注册。这里涉及跨进程操作, 因而传递的参数都是继承自Parcelable的 */ mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders, fullscreenStackBounds, dockedStackBounds); } ... createAndAddWindows(); //这里才是真正将Status Bar显示出来的地方

StarusBarService通过Context.STATUS_BAR_SERVICE启动,这个服务在SystemServer中注册,先看一下SystemServer中的代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
if (!disableSystemUI) { traceBeginAndSlog("StartStatusBarManagerService"); try { statusBar = new StatusBarManagerService(context, wm); ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); } catch (Throwable e) { reportWtf("starting StatusBarManagerService", e); //原来StatusBarManagerService这个家伙注册的 } traceEnd(); }

接下来进一步分析StatusBarManagerService的实现,首先看下其中的registerStatusBar中的代码:

StatusBarManagerService代码路径:

复制代码
1
2
framework/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java

不在之前的SystemUI的路径中

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Override public void registerStatusBar(IStatusBar bar, List<String> iconSlots, List<StatusBarIcon> iconList, int switches[], List<IBinder> binders, Rect fullscreenStackBounds, Rect dockedStackBounds) { enforceStatusBarService(); Slog.i(TAG, "registerStatusBar bar=" + bar); mBar = bar; try { mBar.asBinder().linkToDeath(new DeathRecipient() { @Override public void binderDied() { mBar = null; notifyBarAttachChanged(); } }, 0); } catch (RemoteException e) { } notifyBarAttachChanged(); synchronized (mIcons) { //复制icon列表 for (String slot : mIcons.keySet()) { iconSlots.add(slot); iconList.add(mIcons.get(slot)); } } synchronized (mLock) { switches[0] = gatherDisableActionsLocked(mCurrentUserId, 1); switches[1] = mSystemUiVisibility; switches[2] = mMenuVisible ? 1 : 0; switches[3] = mImeWindowVis; switches[4] = mImeBackDisposition; switches[5] = mShowImeSwitcher ? 1 : 0; switches[6] = gatherDisableActionsLocked(mCurrentUserId, 2); switches[7] = mFullscreenStackSysUiVisibility; switches[8] = mDockedStackSysUiVisibility; binders.add(mImeToken); fullscreenStackBounds.set(mFullscreenStackBounds); dockedStackBounds.set(mDockedStackBounds); } }

从上面的代码看,registerStatusBar的作用主要是:一,为新启动的SystemUI应用赋予当前系统的真实值(比如有多少需要显示的图标);二,通过mBar记录istatusBar对象,它在SystemUI中对应的是CommandQueue。
下面是整理的流程图,大家可以参考一下

最后

以上就是大胆冰淇淋最近收集整理的关于SystemUI模块总结SystemUI模块总结的全部内容,更多相关SystemUI模块总结SystemUI模块总结内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部