概述
SystemUI模块总结
1,SystemUI路径:
SystemUI被放在
framework/base/packages/apps/SystemUI
在该目录的二级目录src/com/android下可看到SystemUI和Keyguard两个目录
SystemUI
Keyguard
由此可见如今将锁屏界面也整合在SystemUI中
2,SystemUI所需权限
从清单文件中可以发现 SystemUI需要建立以下开通权限用以监听开机广播,读写内存和访问所有用户存储状态,监听物理硬件,控制AM,WM,屏保,
锁屏,recent事件,wifi的展示,截屏,快捷设置入口等
<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部分
代码路径:
framework/base/services/java/com/android/server/SystemServer.java
开机后系统会首先启动SystemServer,SystemServer启动后才会带动其他一系列系统服务的启动,也包括SystemUI的启动
public static void main(String[] args) {
new SystemServer().run();
}
在SystemUI的main方法中启用了 SystemServer().run();run方法中主要做了以下操作
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
而在run()方法中做了startBootstrapServices(),startCoreServices(),startOtherServices()三个操作
而在startOtherServices()中做了startSystemUi(context, windowManagerF)的方法
traceBeginAndSlog("StartSystemUI");
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
traceEnd();
startSystemUi具体实现如下,用Intent启动了SystemUIService
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方法
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
......
}
可知在SystemUIService中启动了SystemUIApplication中的startServicesIfNeeded()方法
public void startServicesIfNeeded() {
startServicesIfNeeded(SERVICES);
}
其中SERVICES是一组所有用户共用的SystemUI服务,如下
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是如何启动这一系列服务的
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抽象类
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()方法
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方法
@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中的代码
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代码路径:
framework/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
不在之前的SystemUI的路径中
@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模块总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复