SystemUI 学习(1) — SystemUI发动流程
发动流程首要有两个部分
- 在 framework 中发动 SystemUIService
- 在 SystemUIService 中发动 SystemUI 所需的各种组件
SystemUI 是一个体系运用,即为一个apk。所以它也会有进口 application 。它是由SystemServer 进程发动的。
注:参阅 android-12.0.0_r3 分支中的代码(网站可能会出现无法打开的状况,可以参阅Android官方的(需要外网)AndroidCodeSearch)
framework 中的流程
SystemServer
在 SystemServer.java (frameworks/base/services/java/com/android/server/SystemServer.java) 中
进程进口会发动很多和体系相关的运用、服务。
606 /**
607 * The main entry point from zygote.
608 */
609 public static void main(String[] args) {
610 new SystemServer().run();
611 }
注释中阐明,SystemUI 是由 Zygote 进程发动的。
2929 t.traceBegin("StartSystemUI");
2930 try {
2931 startSystemUi(context, windowManagerF);
2932 } catch (Throwable e) {
2933 reportWtf("starting System UI", e);
2934 }
2935 t.traceEnd();
2936
2937 t.traceEnd(); // startOtherServices
其间 startSystemUi 办法完结如下。
3024 private static void startSystemUi(Context context, WindowManagerService windowManager) {
3025 PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
3026 Intent intent = new Intent();
3027 intent.setComponent(pm.getSystemUiServiceComponent());
3028 intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
3029 //Slog.d(TAG, "Starting service: " + intent);
3030 context.startServiceAsUser(intent, UserHandle.SYSTEM);
3031 windowManager.onSystemUiStarted();
3032 }
这里经过 PackageManagerInternal.getSystemUiServiceComponent() 办法获取到了 SystemUIService 组件,然后经过 startServiceAsUser 办法发动了服务。
PackageManagerInternal
372 /**
373 * @return The SystemUI service component name.
374 */
375 public abstract ComponentName getSystemUiServiceComponent();
这个办法在 PackageManagerInternal中是个抽象办法。考虑 PMS(PackageManagerService)。
里面有一个 PackageManagerInternalImpl 的内部类继承了 PackageManagerInternal 并完结了 getSystemUiServiceComponent() 办法。
27032 private class PackageManagerInternalImpl extends PackageManagerInternal {
...
27449 @Override
27450 public ComponentName getSystemUiServiceComponent() {
27451 return ComponentName.unflattenFromString(mContext
.getResources()
.getString(
27452 com.android.internal.R.string.config_systemUIServiceComponent));
27453 }
其间 config_systemUIServiceComponent 在 frameworks/base/core/res/res/values/config.xml 中
2865 <!-- SystemUi service component -->
2866 <string name="config_systemUIServiceComponent" translatable="false"
2867 >com.android.systemui/com.android.systemui.SystemUIService</string>
小结: framework中的 SystemServer 中的 run 办法发动了体系所需要的各种服务,其间就包含了 SystemUIService。
具体: 经过 PackageManagerInternal 获取到 SystemUIService 的配置称号,然后经过 startServiceAsUser 办法在 startSystemUi 中发动了服务。
SystemUI中的流程
途径 frameworks/base/packages/SystemUI/
SystemUIApplication
onCreate()办法
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "SystemUIApplication created.");
...
...
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
// 一般状况下走这里来,例如开关机发动体系
...
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mBootCompleteCache.isBootComplete()) return;
if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
unregisterReceiver(this);
mBootCompleteCache.setBootComplete();
if (mServicesStarted) {
final int N = mServices.length;
for (int i = 0; i < N; i++) {
mServices[i].onBootCompleted();
}
}
}
}, bootCompletedFilter);
...
} else {
//多用户或其它非体系操作发动 SystemUi
// We don't need to startServices for sub-process that is doing some tasks.
// (screenshots, sweetsweetdesserts or tuner ..)
String processName = ActivityThread.currentProcessName();
ApplicationInfo info = getApplicationInfo();
if (processName != null && processName.startsWith(info.processName + ":")) {
return;
}
// For a secondary user, boot-completed will never be called because it has already
// been broadcasted on startup for the primary SystemUI process. Instead, for
// components which require the SystemUI component to be initialized per-user, we
// start those components now for the current non-system user.
startSecondaryUserServicesIfNeeded();
}
}
-
如果是体系发动的就会进入到这个分支中,注册监听
boot completed的告诉,最后发动彻底发动后就会告诉各个组件onBootCompleted。/** * Makes sure that all the SystemUI services are running. If they are already running, this is a * no-op. This is needed to conditinally start all the services, as we only need to have it in * the main process. * <p>This method must only be called from the main thread.</p> */ public void startServicesIfNeeded() { String[] names = SystemUIFactory.getInstance() .getSystemUIServiceComponents(getResources()); startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names); }定位到
SystemUIFactory中的getSystemUIServiceComponents办法/** Returns the list of system UI components that should be started. */ public String[] getSystemUIServiceComponents(Resources resources) { return resources.getStringArray(R.array.config_systemUIServiceComponents); }找到资源文件中的
config.xml文件,找到config_systemUIServiceComponents。<!-- SystemUI Services: The classes of the stuff to start. --> <string-array name="config_systemUIServiceComponents" translatable="false"> <item>com.android.systemui.util.NotificationChannels</item> <item>com.android.systemui.keyguard.KeyguardViewMediator</item> <item>com.android.systemui.recents.Recents</item> <item>com.android.systemui.volume.VolumeUI</item> <item>com.android.systemui.statusbar.phone.StatusBar</item> <item>com.android.systemui.usb.StorageNotification</item> <item>com.android.systemui.power.PowerUI</item> <item>com.android.systemui.media.RingtonePlayer</item> <item>com.android.systemui.keyboard.KeyboardUI</item> <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item> <item>@string/config_systemUIVendorServiceComponent</item> <item>com.android.systemui.util.leak.GarbageMonitor$Service</item> <item>com.android.systemui.LatencyTester</item> <item>com.android.systemui.globalactions.GlobalActionsComponent</item> <item>com.android.systemui.ScreenDecorations</item> <item>com.android.systemui.biometrics.AuthController</item> <item>com.android.systemui.SliceBroadcastRelayHandler</item> <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item> <item>com.android.systemui.theme.ThemeOverlayController</item> <item>com.android.systemui.accessibility.WindowMagnification</item> <item>com.android.systemui.accessibility.SystemActions</item> <item>com.android.systemui.toast.ToastUI</item> <item>com.android.systemui.wmshell.WMShell</item> </string-array> -
如果不是体系发动,例如多用户登录运用的状况,这时候体系其实现已发动过了,就会走
else的分支进入到startSecondaryUserServicesIfNeeded()用于发动SystemUI所需的服务组件,这个分支是根据用户来发动相应的服务的。同上可已找到,组件名为
config_systemUIServiceComponentsPerUser<!-- SystemUI Services (per user): The classes of the stuff to start for each user. This is a subset of the config_systemUIServiceComponents --> <string-array name="config_systemUIServiceComponentsPerUser" translatable="false"> <item>com.android.systemui.util.NotificationChannels</item> </string-array>
SystemUIService
@Override
public void onCreate() {
super.onCreate();
// Start all of SystemUI
((SystemUIApplication) getApplication()).startServicesIfNeeded();
// Finish initializing dump logic
mLogBufferFreezer.attach(mBroadcastDispatcher);
...
...
// Bind the dump service so we can dump extra info during a bug report
startServiceAsUser(
new Intent(getApplicationContext(), SystemUIAuxiliaryDumpService.class),
UserHandle.SYSTEM);
}
SystemUIApplication.java中
/**
* Makes sure that all the SystemUI services are running. If they are already running,
this is a
* no-op. This is needed to conditinally start all the services,
as we only need to have it in
* the main process.
* <p>This method must only be called from the main thread.</p>
*/
public void startServicesIfNeeded() {
String[] names = SystemUIFactory.getInstance()
.getSystemUIServiceComponents(getResources());
startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
}
getSystemUIServiceComponents与getSystemUIServiceComponentsPerUser流程一致
小结:
SystemServer发动SystemUIService之后,就进入到了运用层中,SystemUIApplication是SystemUI的进口,在onCreate办法中做了一些初始化作业,注册监听告诉等操作;如果是多用户则会发动了一个组件NotificationChannels; 然后就进入到SystemUIService中,它在onCreate办法中也是履行了SystemUIApplication中的startServicesIfNeeded()办法,并把一切的服务都存在mServices数组中。
总结
SystemUI 是一个 persistent 运用,它由操作体系发动,首要流程为
-
Android体系在开机后会创立SystemServer进程,它会发动各种体系所需要的服务,其间就包含SystemUIService。 -
SystemUIService发动后进入到运用层SystemUI中,在SystemUIApplication它首先会初始化监听boot completed等告诉,待体系完结发动后会告诉各个组件onBootCompleted。 - 在进入
SystemUIService中依然履行的SystemUIApplication中的startServicesIfNeeded()办法发动一切SystemUI中的组件。 - 最终的服务发动逻辑都是在
SystemUIApplication里面,并且都保存在mServices数组中。
参阅文章:SystemUI 开发之发动流程
- AndroidCodeSearch
- Android源码在线
