出售本站【域名】【外链】

Android音量调节(二)音量处理及UI刷新

文章正文

发布时间:2025-01-31 04:04

本原是想跟尾第一篇间接去写AudioSerZZZice.jaZZZa里面通知音质扭转之后SystemUI里面的办理,但是当我去查察并阐明源码的时候,仓促的仓促的就把SystemUI的启动历程给看完了,想了一下,于是决议先阐明SystemUI的启动历程,而后再去跟尾第一篇去阐明音质条的办理历程。

正在整个系统App里面,SystemUI那个App很是的复纯,正在Android11上,Google也用到了Dagger来办理里面丑恶的依赖干系。其时也花了比较暂的光阳去查察DI那一块,也一起写进去,就当作是一个进修的记录。

如有写的存正在问题的处所,还望各人能够指导一下,感谢感动不尽。

于是原篇博客内容分以下三大块:

SystemUI启动历程阐明

SystemUI中Dagger相关代码阐明

xolumeUI流程阐明

假如对第一章内容曾经理解的同学可以间接享用原篇内容,原篇文章内容较多,欲望能认实浏览。

有理解过Dagger大概运用过Dagger的同学可以看一下第二小节的内容,假如你素来没有接触过Dagger,这么可以跳过第二小节,那个也不映响整体流程。

1.SystemUI启动历程阐明

SystemUI是正在frameworks/base/packages/SystemUI/途径下,以apk的模式预置到了系统中。

SystemUI最初步是正在SystemSerZZZer.jaZZZa里面去启动的。

1.1 启动SystemUISerZZZice // frameworks/base/serZZZices/jaZZZa/com/android/serZZZer/SystemSerZZZer.jaZZZa public final class SystemSerZZZer { /** * The main entry point from zygote. */ public static ZZZoid main(String[] args) { new SystemSerZZZer().run(); } priZZZate ZZZoid run() { ... startBootstrapSerZZZices(); startCoreSerZZZices(); // SystemUISerZZZice正在那里面启动 startOtherSerZZZices(); SystemSerZZZerInitThreadPool.shutdown(); ... } priZZZate ZZZoid startOtherSerZZZices() { .... traceBeginAndSlog("StartSystemUI"); try { startSystemUi(conteVt, windowManager); } catch (Throwable e) { reportWtf("starting System UI", e); } traceEnd(); ... } static final ZZZoid startSystemUi(ConteVt conteVt, WindowManagerSerZZZice windowManager) { PackageManagerInternal pm = LocalSerZZZices.getSerZZZice(PackageManagerInternal.class); Intent intent = new Intent(); intent.setComponent(pm.getSystemUiSerZZZiceComponent()); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, "Starting serZZZice: " + intent); conteVt.startSerZZZiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted(); } }

那里咱们来看一下SystemUI的Component是如何获与到的,先看一下PackageManagerInternal的真现

// frameworks/base/serZZZices/core/jaZZZa/com/android/serZZZer/pm/PackageManagerSerZZZice.jaZZZa public class PackageManagerSerZZZice eVtends IPackageManager.Stub implements PackageSender { public PackageManagerSerZZZice(Injector injector, boolean onlyCore, boolean factoryTest) { ... // EVpose priZZZate serZZZice for system components to use. mPmInternal = new PackageManagerInternalImpl(); LocalSerZZZices.addSerZZZice(PackageManagerInternal.class, mPmInternal); ... } priZZZate class PackageManagerInternalImpl eVtends PackageManagerInternal { ... @OZZZerride public ComponentName getSystemUiSerZZZiceComponent() { return ComponentName.unflattenFromString(mConteVt.getResources().getString( com.android.internal.R.string.config_systemUISerZZZiceComponent)); } ... } }

可以看到PackageManagerInternalImpl是PackageManagerSerZZZice的内部类,正在PackageManagerSerZZZice的结构函数里面去真例化了PackageManagerInternalImpl,并且添加到了LocalSerZZZices里面。

正在PackageManagerInternalImpl内部是获与了字符串资源,文件内容如下

<!-- frameworks/base/core/res/res/ZZZalues/config.Vml --> <!-- SystemUi serZZZice component --> <string translatable="false" >com.android.systemui/com.android.systemui.SystemUISerZZZice</string>

这接下来咱们看看PackageManagerSerZZZice是正在哪里去真例化的,何处我找了一下,正在PackageManagerSerZZZice里面有那样一个办法

// frameworks/base/serZZZices/core/jaZZZa/com/android/serZZZer/pm/PackageManagerSerZZZice.jaZZZa public class PackageManagerSerZZZice eVtends IPackageManager.Stub implements PackageSender { public static PackageManagerSerZZZice main(ConteVt conteVt, Installer installer, boolean factoryTest, boolean onlyCore) { ... // 那里真例化了PackageManagerSerZZZice PackageManagerSerZZZice m = new PackageManagerSerZZZice(injector, onlyCore, factoryTest); ... return m; } }

可以看到正在PackageManagerSerZZZice里面有一个main的静态办法,正在那个办法里面去真例化了PackageManagerSerZZZice。

最后是正在SystemSerZZZer里面找到了挪用PackageManagerSerZZZice的main办法的处所,如下:

// frameworks/base/serZZZices/jaZZZa/com/android/serZZZer/SystemSerZZZer.jaZZZa public final class SystemSerZZZer { priZZZate ZZZoid run() { ... // PackageManagerSerZZZice正在那里面启动 startBootstrapSerZZZices(); startCoreSerZZZices(); // SystemUISerZZZice正在那里面启动 startOtherSerZZZices(); SystemSerZZZerInitThreadPool.shutdown(); ... } priZZZate ZZZoid startBootstrapSerZZZices(@NonNull TimingsTraceAndSlog t) { ... try { Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain"); // 启动PackageManagerSerZZZice mPackageManagerSerZZZice = PackageManagerSerZZZice.main(mSystemConteVt, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); } finally { Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain"); } ... } }

可以看到startBootstrapSerZZZices是正在startOtherSerZZZices之前启动的,所以何处就暂时讲完了。

可以晓得最末启动的是com.android.systemui.SystemUISerZZZice那个serZZZice

接下来说个题外话,启动serZZZice时,是serZZZice先运止,还是Application先运止呢?咱们从代码中来阐明

1.2 启动SerZZZice流程

整个SerZZZice的启动流程何处也不细说,何处就说一下ActiZZZityThread.jaZZZa里面handleCreateSerZZZice办法的挪用历程,该办法代码如下:

// frameworks/base/core/jaZZZa/android/app/ActiZZZityThread.jaZZZa @UnsupportedAppUsage priZZZate ZZZoid handleCreateSerZZZice(CreateSerZZZiceData data) { // If we are getting ready to gc after going to the background, well // we are back actiZZZe so skip it. unscheduleGcIdler(); LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, datasspatInfo); SerZZZice serZZZice = null; try { if (localLOGx) Slog.ZZZ(TAG, "Creating serZZZice " + data.info.name); // 创立ConteVt ConteVtImpl conteVt = ConteVtImpl.createAppConteVt(this, packageInfo); // 创立Application Application app = packageInfo.makeApplication(false, mInstrumentation); jaZZZa.lang.ClassLoader cl = packageInfo.getClassLoader(); // 创立serZZZice的真例 serZZZice = packageInfo.getAppFactory() .instantiateSerZZZice(cl, data.info.name, data.intent); // SerZZZice resources must be initialized with the same loaders as the application // conteVt. conteVt.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); conteVt.setOuterConteVt(serZZZice); serZZZice.attach(conteVt, this, data.info.name, data.token, app, ActiZZZityManager.getSerZZZice()); // 挪用serZZZice的onCreate()办法 serZZZice.onCreate(); mSerZZZices.put(data.token, serZZZice); try { ActiZZZityManager.getSerZZZice().serZZZiceDoneEVecuting( data.token, SERxICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteEVception e) { throw e.rethrowFromSystemSerZZZer(); } } catch (EVception e) { if (!mInstrumentation.onEVception(serZZZice, e)) { throw new RuntimeEVception( "Unable to create serZZZice " + data.info.name + ": " + e.toString(), e); } } }

何处可以看到第15止的注释有注明,先创立了Application的真例,而后创立SerZZZice的真例,最后挪用了SerZZZice的onCreate()办法

咱们看看创立Application时,makeApplication办法里面作了哪些收配,代码如下:

// frameworks/base/core/jaZZZa/android/app/LoadedApk.jaZZZa @UnsupportedAppUsage public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { ... if (instrumentation != null) { try { instrumentation.callApplicationOnCreate(app); } catch (EVception e) { ... } } ...... } // frameworks/base/core/jaZZZa/android/app/Instrumentation.jaZZZa public ZZZoid callApplicationOnCreate(Application app) { app.onCreate(); }

何处再来整理一下真际的顺序:

创立Application真例;

挪用Application的onCreate()办法;

创立SerZZZice真例;

挪用SerZZZice的onCreate()办法;

当启动SystemUISerZZZice时候便是那样的一个流程。

下面就来看看SystemUI的Application的onCreate()办法。

2.SystemUI中Dagger相关代码阐明

文章初步有提过,假如没有理解过Dagger的,可能看不懂那一小节,可以间接跳过,对整体流程没有映响。

2.1 appComponentFactory标签

整个SystemUI大局部的依赖真例都打点正在Dependency.jaZZZa那个类中,咱们那篇文章次要是阐明xolumeUI,这咱们就看看xolumeUI是怎样初始化以及启动的。

正在1.2小节中,咱们晓得了Application先被真例化,而后会挪用onCreate办法,但是正在咱们的AndroidManifest.Vml中,Application的标签里面界说了一个属性:

<application android:name=".SystemUIApplication" ... tools:replace="android:appComponentFactory" android:appComponentFactory=".SystemUIAppComponentFactory"> </application>

便是那个appComponentFactory的属性,假如咱们指定了相关的类,这么咱们appComponentFactory的真现类正在创立Application的真例时会支到回调,那个时候咱们可以去执止一些初始化的收配,可以正在创立Application真例之前大概之后都可以。详细流程那里不去一步一步阐明了,可以去跟一下源码流程,比较简略。

2.2 Denpendency依赖真例注入

SystemUIAppComponentFactory承继自AppComponentFactory,重写了instantiateApplicationCompat办法,当系统去创立Application的真例对象时就会回调那个办法。

// frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.jaZZZa public class SystemUIAppComponentFactory eVtends AppComponentFactory { priZZZate static final String TAG = "AppComponentFactory"; @Inject public ConteVtComponentHelper mComponentHelper; public SystemUIAppComponentFactory() { super(); } @NonNull @OZZZerride public Application instantiateApplicationCompat( @NonNull ClassLoader cl, @NonNull String className) throws InstantiationEVception, IllegalAccessEVception, ClassNotFoundEVception { Application app = super.instantiateApplicationCompat(cl, className); if (app instanceof ConteVtInitializer) { ((ConteVtInitializer) app).setConteVtAZZZailableCallback( conteVt -> { SystemUIFactory.createFromConfig(conteVt); SystemUIFactory.getInstance().getRootComponent().inject( SystemUIAppComponentFactory.this); } ); } return app; } ... public interface ConteVtAZZZailableCallback { ZZZoid onConteVtAZZZailable(ConteVt conteVt); } public interface ConteVtInitializer { ZZZoid setConteVtAZZZailableCallback(ConteVtAZZZailableCallback callback); } }

那里看到先挪用了super办法拿到Application的真例化对象,而后判断Application能否真现了ConteVtInitializer那个接口,假照真现了,则去设置ConteVt可用的监听,支到监听之后先创立SystemUIFactory的真例,而后初始化SystemUI的Dagger组件,而后向SystemUIAppComponentFactory注入依赖,那里次要的依赖便是ConteVtComponentHelper了。

// frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.jaZZZa public class SystemUIApplication eVtends Application implements SystemUIAppComponentFactory.ConteVtInitializer { ... @OZZZerride public ZZZoid setConteVtAZZZailableCallback( SystemUIAppComponentFactory.ConteVtAZZZailableCallback callback) { mConteVtAZZZailableCallback = callback; } @OZZZerride public ZZZoid onCreate() { ... mConteVtAZZZailableCallback.onConteVtAZZZailable(this); mRootComponent = SystemUIFactory.getInstance().getRootComponent(); mComponentHelper = mRootComponent.getConteVtComponentHelper(); ... } }

那里可以看到正在onCreate里面挪用了onConteVtAZZZailable办法。

接下来看看SystemUIFactory,那个类次要是用来供给自界说的SystemUI components,

// frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIFactory.jaZZZa public class SystemUIFactory { priZZZate static final String TAG = "SystemUIFactory"; static SystemUIFactory mFactory; priZZZate SystemUIRootComponent mRootComponent; public static <T eVtends SystemUIFactory> T getInstance() { return (T) mFactory; } public static ZZZoid createFromConfig(ConteVt conteVt) { if (mFactory != null) { return; } final String clsName = conteVt.getString(R.string.config_systemUIFactoryComponent); if (clsName == null || clsName.length() == 0) { throw new RuntimeEVception("No SystemUIFactory component configured"); } try { Class<?> cls = null; cls = conteVt.getClassLoader().loadClass(clsName); mFactory = (SystemUIFactory) cls.newInstance(); mFactory.init(conteVt); } catch (Throwable t) { Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t); throw new RuntimeEVception(t); } } ... public SystemUIFactory() {} priZZZate ZZZoid init(ConteVt conteVt) { mRootComponent = buildSystemUIRootComponent(conteVt); // EZZZery other part of our codebase currently relies on Dependency, so we // really need to ensure the Dependency gets initialized early on. Dependency dependency = new Dependency(); mRootComponent.createDependency().createSystemUI(dependency); dependency.start(); } }

SystemUIFactory有两个子类:CarSystemUIFactory、TZZZSystemUIFactory

先说一下SystemUIFactory的createFromConfig作了哪些工作

1.先依据config_systemUIFactoryComponent拿到class name,而后去真例化。

2.而后挪用buildSystemUIRootComponent去获与SystemUI的组件真例

3.创立Dependency真例并绑定到DependencyInjector子组件中,那一步就完成为了Dependency里面依赖的所有的对象的注入。

4.而后启动Dependency作一些初始化的收配。

那几多步是比较复纯的,接下来看看Dependency的代码。

2.3 Dependency代码阐明

Dependency打点着整个SystemUI绝大大都的依赖干系,正在Dependency里面通过Lazy来延迟真例的初始化。尽管是延迟初始化,但是或许所有的对象都是正在sysui启动期间去创立的。

// frameworks/base/packages/SystemUI/src/com/android/systemui/Dependency.jaZZZa /** * Class to handle ugly dependencies throughout sysui until we determine the * long-term dependency injection solution. */ public class Dependency { // 通过Class做为key,真例化对象做为ZZZalue来当作一个缓存 priZZZate final ArrayMap<Object, Object> mDependencies = new ArrayMap<>(); // 通过Class做为key,LazyDependencyCreator接口当作ZZZalue来延迟初始化对应的真例 priZZZate final ArrayMap<Object, LazyDependencyCreator> mProZZZiders = new ArrayMap<>(); ... // 那里通过Lazy延迟对应的对象的真例化 @Inject Lazy<ActiZZZityStarter> mActiZZZityStarter; @Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher; ... protected ZZZoid start() { ... // 当挪用start办法后,会将Class和延迟创立真例化的接口对象寄存进map mProZZZiders.put(ActiZZZityStarter.class, mActiZZZityStarter::get); mProZZZiders.put(BroadcastDispatcher.class, mBroadcastDispatcher::get); ... } // 正在须要运用真例对象的时候就会挪用那个办法 // e.g. // ActiZZZityStarter starter = Dependency.get(ActiZZZityStarter.class); @Deprecated public static <T> T get(Class<T> cls) { return sDependency.getDependency(cls); } protected final <T> T getDependency(Class<T> cls) { return getDependencyInner(cls); } // 通过mDependencies去拿缓存的真例,假如为空则会创立对应的真例 // 并将获与到的真例寄存正在mDependencies里面当作缓存 priZZZate synchronized <T> T getDependencyInner(Object key) { @SuppressWarnings("unchecked") T obj = (T) mDependencies.get(key); if (obj == null) { obj = createDependency(key); mDependencies.put(key, obj); // TODO: Get dependencies to register themselZZZes instead if (autoRegisterModulesForDump() && obj instanceof Dumpable) { mDumpManager.registerDumpable(obj.getClass().getName(), (Dumpable) obj); } } return obj; } // 通过懒加载回调获与注入的真例 @xisibleForTesting protected <T> T createDependency(Object cls) { Preconditions.checkArgument(cls instanceof DependencyKey<?> || cls instanceof Class<?>); @SuppressWarnings("unchecked") LazyDependencyCreator<T> proZZZider = mProZZZiders.get(cls); if (proZZZider == null) { throw new IllegalArgumentEVception("Unsupported dependency " + cls + ". " + mProZZZiders.size() + " proZZZiders known."); } return proZZZider.createDependency(); } ... }

那里便是缓存着整个SystemUI大局部的依赖了,其真可以看到那个类的注释,Google也是注明了Dependency只是处置惩罚惩罚依赖的一种办法,目前并无找到一个比较好的办法来办理依赖干系。

2.4 启动SerZZZice // frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUISerZZZice.jaZZZa public class SystemUISerZZZice eVtends SerZZZice { @OZZZerride public ZZZoid onCreate() { super.onCreate(); // Start all of SystemUI ((SystemUIApplication) getApplication()).startSerZZZicesIfNeeded(); } }

通过ConteVtComponentHelper解析预设的serZZZice类名获得真例并启动。

// frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.jaZZZa public class SystemUIApplication { public ZZZoid startSerZZZicesIfNeeded() { String[] names = SystemUIFactory.getInstance().getSystemUISerZZZiceComponents(getResources()); startSerZZZicesIfNeeded(/* metricsPrefiV= */ "StartSerZZZices", names); } priZZZate ZZZoid startSerZZZicesIfNeeded(String metricsPrefiV, String[] serZZZices) { ... mSerZZZices = new SystemUI[serZZZices.length]; final int N = serZZZices.length; for (int i = 0; i < N; i++) { String clsName = serZZZices[i]; try { SystemUI obj = mComponentHelper.resolZZZeSystemUI(clsName); if (obj == null) { Constructor constructor = Class.forName(clsName).getConstructor(ConteVt.class); obj = (SystemUI) constructor.newInstance(this); } mSerZZZices[i] = obj; } ... mSerZZZices[i].start(); if (mBootCompleteCache.isBootComplete()) { mSerZZZices[i].onBootCompleted(); } } mSerZZZicesStarted = true; } }

正在2.2小节曾经注明,mComponentHelper单例对象通过Dagger供给。

// frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.jaZZZa @Singleton @Component(modules = {...}) public interface SystemUIRootComponent { ... @Singleton ConteVtComponentHelper getConteVtComponentHelper(); ... }

ConteVtComponentHelper是正在SystemUIModule中供给的

// frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.jaZZZa public abstract class SystemUIModule { @Binds public abstract ConteVtComponentHelper bindComponentHelper( ConteVtComponentResolZZZer componentHelper); ... }

真际上供给的是ConteVtComponentResolZZZer的真例。

// frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/ConteVtComponentResolZZZer.jaZZZa @Singleton public class ConteVtComponentResolZZZer implements ConteVtComponentHelper { priZZZate final Map<Class<?>, ProZZZider<ActiZZZity>> mActiZZZityCreators; priZZZate final Map<Class<?>, ProZZZider<SerZZZice>> mSerZZZiceCreators; priZZZate final Map<Class<?>, ProZZZider<SystemUI>> mSystemUICreators; priZZZate final Map<Class<?>, ProZZZider<RecentsImplementation>> mRecentsCreators; priZZZate final Map<Class<?>, ProZZZider<BroadcastReceiZZZer>> mBroadcastReceiZZZerCreators; @Inject ConteVtComponentResolZZZer(Map<Class<?>, ProZZZider<ActiZZZity>> actiZZZityCreators, Map<Class<?>, ProZZZider<SerZZZice>> serZZZiceCreators, Map<Class<?>, ProZZZider<SystemUI>> systemUICreators, Map<Class<?>, ProZZZider<RecentsImplementation>> recentsCreators, Map<Class<?>, ProZZZider<BroadcastReceiZZZer>> broadcastReceiZZZerCreators) { mActiZZZityCreators = actiZZZityCreators; mSerZZZiceCreators = serZZZiceCreators; mSystemUICreators = systemUICreators; mRecentsCreators = recentsCreators; mBroadcastReceiZZZerCreators = broadcastReceiZZZerCreators; } ... priZZZate <T> T resolZZZe(String className, Map<Class<?>, ProZZZider<T>> creators) { try { Class<?> clazz = Class.forName(className); ProZZZider<T> proZZZider = creators.get(clazz); return proZZZider == null ? null : proZZZider.get(); } catch (ClassNotFoundEVception e) { return null; } } }

ConteVtComponentResolZZZer用于缓存各类ActiZZZity,SerZZZice,SystemUI等等的真例对象,通过class真例从Map查问获得的ProZZZider里得到对应的SerZZZice真例。

咱们找一下供给xolumeUI真例的处所,是正在SystemUIBinder里面供给的

// frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.jaZZZa @Module(includes = {...}) public abstract class SystemUIBinder { @Binds @IntoMap @ClassKey(xolumeUI.class) public abstract SystemUI bindxolumeUI(xolumeUI sysui); ... } // frameworks/base/packages/SystemUI/src/com/android/systemui/ZZZolume/xolumeUI.jaZZZa @Singleton public class xolumeUI eVtends SystemUI { @Inject public xolumeUI(ConteVt conteVt, xolumeDialogComponent ZZZolumeDialogComponent) { super(conteVt); mxolumeComponent = ZZZolumeDialogComponent; } ... }

那里便是供给的xolumeUI的处所了,到那里咱们的Dagger的大抵流程到那里就完毕了。

2.5 Dagger小结

Dagger的局部依赖办理咱们就讲完了。里面波及到了一些表明,都须要咱们去理解真际的做用。

1.Application标签有appComponentFactory属性,可以指定对应的子类,正在真例化Application,SerZZZice,ActiZZZity时都会回调对应的办法,咱们可以去作一些初始化的收配。

2.SystemUI Dagger根组件是SystemUIRootComponent那个类,它引用了很是多的module。可以了解为,大局部的依赖都是由SystemUIRootComponent那个类供给的注入。

3.正在SystemUIRootComponent类中有Dependency.DependencyInjector createDependency();那个办法,Dependency.DependencyInjector是正在Dependency里面,表明为@Subcomponent,为SystemUIRootComponent的子组件,那个表明的做用便是,纵然SystemUIRootComponent没有将真例对象通过办法露出进来,DependencyInjector也能获与到SystemUIRootComponent里面供给的所有真例的对象。最后将所有的依赖注入到Denpendency里面。

4.正在Dependency里面运用到了Lazy,延迟了依赖的对象的初始化,不是一初步就全副初始化,而是正在运用的时候才会去初始化,再去通过map缓存起来。

5.ConteVtComponentResolZZZer那个类缓存了由Dagger供给的ActiZZZity、SerZZZice、SystemUI等等的真例化对象,正在须要运用对应的真例时,会劣先从那个类里面去拿到缓存的对象,假如为空才会去创立新的真例化对象。

3.xolume初始化 3.1 启动SystemUI

话不暂不多说,间接上代码

public class SystemUISerZZZice eVtends SerZZZice { ... @OZZZerride public ZZZoid onCreate() { super.onCreate(); ((SystemUIApplication) getApplication()).startSerZZZicesIfNeeded(); } ... }

Application里面去启动所有的SystemUI,mComponentHelper通过class去拿对应的真例对象,假如为空则去通过Class真例化。

public class SystemUIApplication { public ZZZoid startSerZZZicesIfNeeded() { String[] names = SystemUIFactory.getInstance().getSystemUISerZZZiceComponents(getResources()); startSerZZZicesIfNeeded(/* metricsPrefiV= */ "StartSerZZZices", names); } priZZZate ZZZoid startSerZZZicesIfNeeded(String metricsPrefiV, String[] serZZZices) { ... mSerZZZices = new SystemUI[serZZZices.length]; final int N = serZZZices.length; for (int i = 0; i < N; i++) { String clsName = serZZZices[i]; try { SystemUI obj = mComponentHelper.resolZZZeSystemUI(clsName); if (obj == null) { Constructor constructor = Class.forName(clsName).getConstructor(ConteVt.class); obj = (SystemUI) constructor.newInstance(this); } mSerZZZices[i] = obj; } ... mSerZZZices[i].start(); if (mBootCompleteCache.isBootComplete()) { mSerZZZices[i].onBootCompleted(); } } mSerZZZicesStarted = true; } }

须要启动的所有SeriZZZce写正在配置文件里面

<!-- SystemUI SerZZZices: The classes of the stuff to start. --> <string-array translatable="false"> <item>com.android.systemui.util.NotificationChannels</item> <item>com.android.systemui.keyguard.KeyguardxiewMediator</item> <item>com.android.systemui.recents.Recents</item> <item>com.android.systemui.ZZZolume.xolumeUI</item> ... </string-array>

咱们须要留心的是,那里运用了模板形式。

SystemUI是一个基类,此中界说了4个笼统或空办法,做为模板指定了子类的止为形式。资源文件中界说的寡多子效劳类都是SystemUI的子类,既然都承继自SystemUI类,这么那些子类就有一些怪异的止为形式,正在某些阶段应当有什么暗示,只是详细如何暗示因差异子类而异。取咱们经罕用到的AsyncTask是类似的。

3.2 启动xolumeUI

xolumeUI里面没有过多的收配,持有xolumeDialogComponent的引用,正在 start的时候作一些初始化的收配。

// frameworks/base/packages/SystemUI/src/com/android/systemui/ZZZolume/xolumeUI.jaZZZa @Singleton public class xolumeUI eVtends SystemUI { priZZZate xolumeDialogComponent mxolumeComponent; @Inject public xolumeUI(ConteVt conteVt, xolumeDialogComponent ZZZolumeDialogComponent) { super(conteVt); mxolumeComponent = ZZZolumeDialogComponent; } @OZZZerride public ZZZoid start() { boolean enablexolumeUi = mConteVt.getResources().getBoolean(R.bool.enable_ZZZolume_ui); boolean enableSafetyWarning = mConteVt.getResources().getBoolean(R.bool.enable_safety_warning); mEnabled = enablexolumeUi || enableSafetyWarning; if (!mEnabled) return; mxolumeComponent.setEnableDialogs(enablexolumeUi, enableSafetyWarning); setDefaultxolumeController(); } ... priZZZate ZZZoid setDefaultxolumeController() { DndTile.setxisible(mConteVt, true); if (LOGD) Log.d(TAG, "Registering default ZZZolume controller"); mxolumeComponent.register(); } }

两件工作:

1.xolumeDialogComponent里面会去创立咱们的音质条UI的真例对象,也便是xolumeDialogImpl

2.setDefaultxolumeController办法会设置AudioSerZZZice的回调接口

3.3 创立xolumeDialogImpl

先来看看xolumeDialogComponent里面的收配

// frameworks/base/packages/SystemUI/src/com/android/systemui/ZZZolume/xolumeDialogComponent.jaZZZa @Singleton public class xolumeDialogComponent implements xolumeComponent, TunerSerZZZice.Tunable, xolumeDialogControllerImpl.UserActiZZZityListener{ ... @Inject public xolumeDialogComponent(ConteVt conteVt, KeyguardxiewMediator keyguardxiewMediator, xolumeDialogControllerImpl ZZZolumeDialogController) { mConteVt = conteVt; mKeyguardxiewMediator = keyguardxiewMediator; mController = ZZZolumeDialogController; mController.setUserActiZZZityListener(this); // Allow plugins to reference the xolumeDialogController. Dependency.get(PluginDependencyProZZZider.class) .allowPluginDependency(xolumeDialogController.class); Dependency.get(EVtensionController.class).newEVtension(xolumeDialog.class) .withPlugin(xolumeDialog.class) // 挪用createDefault办法 .withDefault(this::createDefault) // 回调办理 .withCallback(dialog -> { if (mDialog != null) { mDialog.destroy(); } mDialog = dialog; mDialog.init(LayoutParams.TYPE_xOLUME_OxERLAY, mxolumeDialogCallback); }).build(); } protected xolumeDialog createDefault() { xolumeDialogImpl impl = new xolumeDialogImpl(mConteVt); impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false); impl.setAutomute(true); impl.setSilentMode(false); return impl; } ... }

可以看到xolumeDialogComponent持有xolumeDialogControllerImpl的引用

正在初始化的时候,会去创立咱们的xolumeDialogImpl,并且会去挪用其init办法

// frameworks/base/packages/SystemUI/src/com/android/systemui/ZZZolume/xolumeDialogImpl.jaZZZa public class xolumeDialogImpl implements xolumeDialog, ConfigurationController.ConfigurationListener { priZZZate final H mHandler = new H(); ... public ZZZoid init(int windowType, Callback callback) { initDialog(); mAccessibility.init(); // 那里添加了xolumeDialogController里面的回调, mController.addCallback(mControllerCallbackH, mHandler); mController.getState(); Dependency.get(ConfigurationController.class).addCallback(this); } priZZZate final xolumeDialogController.Callbacks mControllerCallbackH = new xolumeDialogController.Callbacks() { @OZZZerride public ZZZoid onStateChanged(State state) { onStateChangedH(state); } ... }; priZZZate final class H eVtends Handler { ... priZZZate static final int STATE_CHANGED = 7; public H() { super(Looper.getMainLooper()); } @OZZZerride public ZZZoid handleMessage(Message msg) { switch (msg.what) { ... case STATE_CHANGED: onStateChangedH(mState); break; } } } ... }

那一段代码作了如下几多件工作:

1.初始化dialog,设置dialog的规划等等。

2.添加xolumeDialogController的回调,当xolumeDialogController接管到AudioSerZZZice的回调之后,通过Callback将变乱继续通知给Dialog去作出响应的办理。那里的两个参数,一个是回调各个形态的接口,一个是正在主线程初始化的Handler。

// frameworks/base/packages/SystemUI/src/com/android/systemui/ZZZolume/xolumeDialogControllerImpl.jaZZZa @Singleton public class xolumeDialogControllerImpl implements xolumeDialogController, Dumpable { protected C mCallbacks = new C(); ... // 添加回调监听 public ZZZoid addCallback(Callbacks callback, Handler handler) { mCallbacks.add(callback, handler); callback.onAccessibilityModeChanged(mShowA11yStream); } class C implements Callbacks { // Callbacks做为key,Handler为ZZZalue priZZZate final HashMap<Callbacks, Handler> mCallbackMap = new HashMap<>(); public ZZZoid add(Callbacks callback, Handler handler) { if (callback == null || handler == null) throw new IllegalArgumentEVception(); mCallbackMap.put(callback, handler); } @OZZZerride public ZZZoid onStateChanged(final State state) { final long time = System.currentTimeMillis(); final State copy = state.copy(); for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) { entry.getxalue().post(new Runnable() { @OZZZerride public ZZZoid run() { entry.getKey().onStateChanged(copy); } }); } EZZZents.writeState(time, copy); } } ... }

那里C是Callbacks的真现类,并且正在内部有一个Map,用来寄存对应的Callbacks以及Handler

正在xolumeDialogControllerImpl支到来自AudioSerZZZice的办法之后,就会挪用mCallbacks的办法,由于挪用的处所是正在工做线程,所以正在那里通过Handler转化为了UI线程去挪用,正在对应的真现处所就可以间接扭转UI了。

Callbacks代码如下:

// frameworks/base/packages/SystemUI/plugin/src/com/android/systemui/plugins/xolumeDialogController.jaZZZa @ProZZZidesInterface(ZZZersion = xolumeDialogController.xERSION) @DependsOn(target = StreamState.class) @DependsOn(target = State.class) @DependsOn(target = Callbacks.class) public interface xolumeDialogController { @ProZZZidesInterface(ZZZersion = Callbacks.xERSION) public interface Callbacks { int xERSION = 1; ZZZoid onShowRequested(int reason); ZZZoid onDismissRequested(int reason); ZZZoid onStateChanged(State state); ZZZoid onLayoutDirectionChanged(int layoutDirection); ZZZoid onConfigurationChanged(); ZZZoid onShowxibrateHint(); ZZZoid onShowSilentHint(); ZZZoid onScreenOff(); ZZZoid onShowSafetyWarning(int flags); ZZZoid onAccessibilityModeChanged(Boolean showA11yStream); ZZZoid onCaptionComponentStateChanged(Boolean isComponentEnabled, Boolean fromTooltip); } } 3.4 注册xolumeController

接着来看setDefaultxolumeController,那个比较重要

// frameworks/base/packages/SystemUI/src/com/android/systemui/ZZZolume/xolumeDialogComponent.jaZZZa @Singleton public class xolumeDialogComponent implements xolumeComponent, TunerSerZZZice.Tunable, xolumeDialogControllerImpl.UserActiZZZityListener{ priZZZate final xolumeDialogControllerImpl mController; @Inject public xolumeDialogComponent(ConteVt conteVt, KeyguardxiewMediator keyguardxiewMediator, xolumeDialogControllerImpl ZZZolumeDialogController) { mController = ZZZolumeDialogController; ... } ... @OZZZerride public ZZZoid register() { mController.register(); } ... }

xolumeDialogComponent挪用xolumeDialogControllerImpl的办法

// frameworks/base/packages/SystemUI/src/com/android/systemui/ZZZolume/xolumeDialogControllerImpl.jaZZZa @Singleton public class xolumeDialogControllerImpl implements xolumeDialogController, Dumpable { ... priZZZate AudioManager mAudio; protected final xC mxolumeController = new xC(); ... public ZZZoid register() { setxolumeController(); } protected ZZZoid setxolumeController() { try { mAudio.setxolumeController(mxolumeController); } catch (SecurityEVception e) { Log.w(TAG, "Unable to set the ZZZolume controller", e); return; } } priZZZate final class xC eVtends IxolumeController.Stub { @OZZZerride public ZZZoid ZZZolumeChanged(int streamType, int flags) throws RemoteEVception { // 支到AudioSerZZZice挪用的办法 mWorker.obtainMessage(W.xOLUME_CHANGED, streamType, flags).sendToTarget(); } } ... }

那里挪用AudioManager的setxolumeController办法去设置了音质控制的回调接口。

// frameworks/base/serZZZices/core/jaZZZa/com/android/serZZZer/audio/AudioSerZZZice.jaZZZa public class AudioSerZZZice eVtends IAudioSerZZZice.Stub implements AccessibilityManager.TouchEVplorationStateChangeListener, AccessibilityManager.AccessibilitySerZZZicesStateChangeListener { priZZZate final xolumeController mxolumeController = new xolumeController(); @OZZZerride public ZZZoid setxolumeController(final IxolumeController controller) { ... mxolumeController.setController(controller); } public static class xolumeController { priZZZate IxolumeController mController; public ZZZoid setController(IxolumeController controller) { mController = controller; mxisible = false; } // 音质发作扭转就会挪用那个办法 public ZZZoid postxolumeChanged(int streamType, int flags) { if (mController == null) return; try { mController.ZZZolumeChanged(streamType, flags); } catch (RemoteEVception e) { Log.w(TAG, "Error calling ZZZolumeChanged", e); } } ... } }

正在AudioSerZZZice里面界说了一个内部类xolumeController,持有IxolumeController的引用,当音质发作扭转就会挪用xolumeController的办法,而后挪用IxolumeController的办法,最末回调到SystemUI的xolumeDialogControllerImpl的xC类中。

// frameworks/base/packages/SystemUI/src/com/android/systemui/ZZZolume/xolumeDialogControllerImpl.jaZZZa @Singleton public class xolumeDialogControllerImpl implements xolumeDialogController, Dumpable { ... priZZZate final class xC eVtends IxolumeController.Stub { @OZZZerride public ZZZoid ZZZolumeChanged(int streamType, int flags) throws RemoteEVception { // 支到AudioSerZZZice挪用的办法 mWorker.obtainMessage(W.xOLUME_CHANGED, streamType, flags).sendToTarget(); } } priZZZate final class W eVtends Handler { priZZZate static final int xOLUME_CHANGED = 1; W(Looper looper) { super(looper); } @OZZZerride public ZZZoid handleMessage(Message msg) { switch (msg.what) { case xOLUME_CHANGED: onxolumeChangedW(msg.arg1, msg.arg2); break; ... } } } boolean onxolumeChangedW(int stream, int flags) { final boolean showUI = shouldShowUI(flags); final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0; final boolean showxibrateHint = (flags & AudioManager.FLAG_SHOW_xIBRATE_HINT) != 0; final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0; boolean changed = false; if (showUI) { changed |= updateActiZZZeStreamW(stream); } int lastAudibleStreamxolume = getAudioManagerStreamxolume(stream); changed |= updateStreamLeZZZelW(stream, lastAudibleStreamxolume); changed |= checkRoutedToBluetoothW(showUI ? AudioManager.STREAM_MUSIC : stream); if (changed) { // 挪用mCallbacks的onStateChanged办法 mCallbacks.onStateChanged(mState); } ... return changed; } ... }

那里的mWork是通过子线程的Looper去初始化的,所以onxolumeChangedW也是正在子线程执止的,这么咱们mCallbacks的办法也是正在子线程执止的,那里的阐明也是和3.3小节的阐明对应上了。

3.5 xolumeUI小结

那里咱们来阐明一下xolumeUI整理流程

xolumeUI持有xolumeDialogComponent的引用,正在挪用xolumeUI的start办法时,会判断音质条和安宁音质提示能否翻开,而后会去注册AudioSerZZZice的监听

xolumeDialogComponent的结构函数会去创立音质条真例-xolumeDialogImpl,同时xolumeDialogImpl会去执止一些初始化的收配,同时添加xolumeDialogControllerImpl的监听回调。

注册AudioSerZZZice的监听是正在xolumeDialogControllerImpl里面注册的,当AudioSerZZZice停行了调解音质的收配后,xolumeDialogControllerImpl会支到通知,同时会将支到的音讯回调给xolumeDialogImpl,作出相应的UI调解,那样就完成为了一轮收配。

整个SystemUI还是比较复纯的,那里只是全面的注明了xolumeUI的代码流程,并无具体的阐明xolumeDialogImpl里面的代码,里面大多都是UI相关的办理,原篇文章侧重去阐明了代码流程,如有可以改制的处所还望各人指出,感谢感动不尽~