Merge "Adding some Shell documentation" into tm-qpr-dev am: 5ff3c0e94c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19230676 Change-Id: I06610ee9728720bd2fe7e230bf9b1734c2960b15 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -1,13 +0,0 @@
|
|||||||
The dagger modules in this directory can be included by the host SysUI using the Shell library for
|
|
||||||
explicity injection of Shell components. Apps using this library are not required to use these
|
|
||||||
dagger modules for setup, but it is recommended for them to include them as needed.
|
|
||||||
|
|
||||||
The modules are currently inherited as such:
|
|
||||||
|
|
||||||
+- WMShellBaseModule (common shell features across SysUI)
|
|
||||||
|
|
|
||||||
+- WMShellModule (handheld)
|
|
||||||
|
|
|
||||||
+- TvPipModule (tv pip)
|
|
||||||
|
|
|
||||||
+- TvWMShellModule (tv)
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Window Manager Shell Readme
|
||||||
|
|
||||||
|
The following docs present more detail about the implementation of the WMShell library (in no
|
||||||
|
particular order):
|
||||||
|
|
||||||
|
1) [What is the Shell](overview.md)
|
||||||
|
2) [Integration with SystemUI & Launcher](sysui.md)
|
||||||
|
3) [Usage of Dagger](dagger.md)
|
||||||
|
4) [Threading model in the Shell](threading.md)
|
||||||
|
5) [Making changes in the Shell](changes.md)
|
||||||
|
6) [Extending the Shell for Products/OEMs](extending.md)
|
||||||
|
7) [Debugging in the Shell](debugging.md)
|
||||||
|
8) [Testing in the Shell](testing.md)
|
||||||
|
|
||||||
|
Todo
|
||||||
|
- Per-feature docs
|
||||||
|
- Feature flagging
|
||||||
|
- Best practices
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Making changes in the Shell
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code reviews
|
||||||
|
|
||||||
|
In addition to the individual reviewers who are most familiar with the changes you are making,
|
||||||
|
please also add [wm-code-reviewers@google.com](http://g/wm-code-reviewers) to keep other WM folks
|
||||||
|
in the loop.
|
||||||
|
|
||||||
|
## Adding new code
|
||||||
|
|
||||||
|
### Internal Shell utility classes
|
||||||
|
If the new component is used only within the WMShell library, then there are no special
|
||||||
|
considerations, go ahead and add it (in the `com.android.wm.shell.common` package for example)
|
||||||
|
and make sure the appropriate [unit tests](testing.md) are added.
|
||||||
|
|
||||||
|
### Internal Shell components
|
||||||
|
If the new component is to be used by other components/features within the Shell library, then
|
||||||
|
you can create an appropriate package for this component to add your new code. The current
|
||||||
|
pattern is to have a single `<Component name>Controller` that handles the initialization of the
|
||||||
|
component.
|
||||||
|
|
||||||
|
As mentioned in the [Dagger usage](dagger.md) docs, you need to determine whether it should go into:
|
||||||
|
- `WMShellBaseModule` for components that other base & product components will depend on
|
||||||
|
- or `WMShellModule`, `TvWmShellModule`, etc. for product specific components that no base
|
||||||
|
components depend on
|
||||||
|
|
||||||
|
### SysUI accessible components
|
||||||
|
In addition to doing the above, you will also need to provide an interface for calling to SysUI
|
||||||
|
from the Shell and vice versa. The current pattern is to have a parallel `Optional<Component name>`
|
||||||
|
interface that the `<Component name>Controller` implements and handles on the main Shell thread.
|
||||||
|
|
||||||
|
In addition, because components accessible to SysUI injection are explicitly listed, you'll have to
|
||||||
|
add an appropriate method in `WMComponent` to get the interface and update the `Builder` in
|
||||||
|
`SysUIComponent` to take the interface so it can be injected in SysUI code. The binding between
|
||||||
|
the two is done in `SystemUIFactory#init()` which will need to be updated as well.
|
||||||
|
|
||||||
|
### Launcher accessible components
|
||||||
|
Because Launcher is not a part of SystemUI and is a separate process, exposing controllers to
|
||||||
|
Launcher requires a new AIDL interface to be created and implemented by the controller. The
|
||||||
|
implementation of the stub interface in the controller otherwise behaves similar to the interface
|
||||||
|
to SysUI where it posts the work to the main Shell thread.
|
||||||
|
|
||||||
|
### Component initialization
|
||||||
|
To initialize the component:
|
||||||
|
- On the Shell side, update `ShellInitImpl` to get a signal to initialize when the SysUI is started
|
||||||
|
- On the SysUI side, update `WMShell` to setup any bindings for the component that depend on
|
||||||
|
SysUI code
|
||||||
|
|
||||||
|
### General Do's & Dont's
|
||||||
|
Do:
|
||||||
|
- Do add unit tests for all new components
|
||||||
|
- Do keep controllers simple and break them down as needed
|
||||||
|
|
||||||
|
Don't:
|
||||||
|
- **Don't** do initialization in the constructor, only do initialization in the init callbacks.
|
||||||
|
Otherwise it complicates the building of the dependency graph.
|
||||||
|
- **Don't** create dependencies from base-module components on specific features (the base module
|
||||||
|
is intended for use with all products)
|
||||||
|
- Try adding a mechanism to register and listen for changes from the base module component instead
|
||||||
|
- **Don't** add blocking synchronous calls in the SysUI interface between Shell & SysUI
|
||||||
|
- Try adding a push-mechanism to share data, or an async callback to request data
|
||||||
|
|
||||||
|
### Exposing shared code for use in Launcher
|
||||||
|
Launcher doesn't currently build against the Shell library, but needs to have access to some shared
|
||||||
|
AIDL interfaces and constants. Currently, all AIDL files, and classes under the
|
||||||
|
`com.android.wm.shell.util` package are automatically built into the `SystemUISharedLib` that
|
||||||
|
Launcher uses.
|
||||||
|
|
||||||
|
If the new code doesn't fall into those categories, they can be added explicitly in the Shell's
|
||||||
|
[Android.bp](frameworks/base/libs/WindowManager/Shell/Android.bp) file under the
|
||||||
|
`wm_shell_util-sources` filegroup.
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# Usage of Dagger in the Shell library
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
Dagger is not required to use the Shell library, but it has a lot of obvious benefits:
|
||||||
|
|
||||||
|
- Not having to worry about how to instantiate all the dependencies of a class, especially as
|
||||||
|
dependencies evolve (ie. product controller depends on base controller)
|
||||||
|
- Can create boundaries within the same app to encourage better code modularity
|
||||||
|
|
||||||
|
As such, the Shell also tries to provide some reasonable out-of-the-box modules for use with Dagger.
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
|
||||||
|
All the Dagger related code in the Shell can be found in the `com.android.wm.shell.dagger` package,
|
||||||
|
this is intentional as it keeps the "magic" in a single location. The explicit nature of how
|
||||||
|
components in the shell are provided is as a result a bit more verbose, but it makes it easy for
|
||||||
|
developers to jump into a few select files and understand how different components are provided
|
||||||
|
(especially as products override components).
|
||||||
|
|
||||||
|
The module dependency tree looks a bit like:
|
||||||
|
- [WMShellConcurrencyModule](frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java)
|
||||||
|
(provides threading-related components)
|
||||||
|
- [WMShellBaseModule](frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java)
|
||||||
|
(provides components that are likely common to all products, ie. DisplayController,
|
||||||
|
Transactions, etc.)
|
||||||
|
- [WMShellModule](frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java)
|
||||||
|
(phone/tablet specific components only)
|
||||||
|
- [TvPipModule](frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java)
|
||||||
|
(PIP specific components for TV)
|
||||||
|
- [TvWMShellModule](frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java)
|
||||||
|
(TV specific components only)
|
||||||
|
- etc.
|
||||||
|
|
||||||
|
Ideally features could be abstracted out into their own modules and included as needed by each
|
||||||
|
product.
|
||||||
|
|
||||||
|
## Overriding base components
|
||||||
|
|
||||||
|
In some rare cases, there are base components that can change behavior depending on which
|
||||||
|
product it runs on. If there are hooks that can be added to the component, that is the
|
||||||
|
preferable approach.
|
||||||
|
|
||||||
|
The alternative is to use the [@DynamicOverride](frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/DynamicOverride.java)
|
||||||
|
annotation to allow the product module to provide an implementation that the base module can
|
||||||
|
reference. This is most useful if the existence of the entire component is controlled by the
|
||||||
|
product and the override implementation is optional (there is a default implementation). More
|
||||||
|
details can be found in the class's javadoc.
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Debugging in the Shell
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Logging & ProtoLogs
|
||||||
|
|
||||||
|
The interactions in the Shell can be pretty complicated, so having good logging is crucial to
|
||||||
|
debugging problems that arise (especially in dogfood). The Shell uses the same efficient Protolog
|
||||||
|
mechanism as WM Core, which can be enabled at runtime on debug devices.
|
||||||
|
|
||||||
|
**TLDR** Don’t use Logs or Slogs except for error cases, Protologs are much more flexible,
|
||||||
|
easy to add and easy to use
|
||||||
|
|
||||||
|
### Adding a new ProtoLog
|
||||||
|
Update `ShellProtoLogGroup` to include a new log group (ie. NEW_FEATURE) for the content you want to
|
||||||
|
log. ProtoLog log calls mirror Log.v/d/e(), and take a format message and arguments:
|
||||||
|
```java
|
||||||
|
ProtoLog.v(NEW_FEATURE, "Test log w/ params: %d %s", 1, “a”)
|
||||||
|
```
|
||||||
|
This code itself will not compile by itself, but the `protologtool` will preprocess the file when
|
||||||
|
building to check the log state (is enabled) before printing the print format style log.
|
||||||
|
|
||||||
|
**Notes**
|
||||||
|
- ProtoLogs currently only work from soong builds (ie. via make/mp). We need to reimplement the
|
||||||
|
tool for use with SysUI-studio
|
||||||
|
- Non-text ProtoLogs are not currently supported with the Shell library (you can't view them with
|
||||||
|
traces in Winscope)
|
||||||
|
|
||||||
|
### Enabling ProtoLog command line logging
|
||||||
|
Run these commands to enable protologs for both WM Core and WM Shell to print to logcat.
|
||||||
|
```shell
|
||||||
|
adb shell wm logging enable-text NEW_FEATURE
|
||||||
|
adb shell wm logging disable-text NEW_FEATURE
|
||||||
|
```
|
||||||
|
|
||||||
|
## Winscope Tracing
|
||||||
|
|
||||||
|
The Winscope tool is extremely useful in determining what is happening on-screen in both
|
||||||
|
WindowManager and SurfaceFlinger. Follow [go/winscope](http://go/winscope-help) to learn how to
|
||||||
|
use the tool.
|
||||||
|
|
||||||
|
In addition, there is limited preliminary support for Winscope tracing componetns in the Shell,
|
||||||
|
which involves adding trace fields to [wm_shell_trace.proto](frameworks/base/libs/WindowManager/Shell/proto/wm_shell_trace.proto)
|
||||||
|
file and ensure it is updated as a part of `WMShell#writeToProto`.
|
||||||
|
|
||||||
|
Tracing can be started via the shell command (to be added to the Winscope tool as needed):
|
||||||
|
```shell
|
||||||
|
adb shell cmd statusbar tracing start
|
||||||
|
adb shell cmd statusbar tracing stop
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dumps
|
||||||
|
|
||||||
|
Because the Shell library is built as a part of SystemUI, dumping the state is currently done as a
|
||||||
|
part of dumping the SystemUI service. Dumping the Shell specific data can be done by specifying the
|
||||||
|
WMShell SysUI service:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
adb shell dumpsys activity service SystemUIService WMShell
|
||||||
|
```
|
||||||
|
|
||||||
|
If information should be added to the dump, make updates to:
|
||||||
|
- `WMShell` if you are dumping SysUI state
|
||||||
|
- `ShellCommandHandler` if you are dumping Shell state
|
||||||
|
|
||||||
|
## Debugging in Android Studio
|
||||||
|
|
||||||
|
If you are using the [go/sysui-studio](http://go/sysui-studio) project, then you can debug Shell
|
||||||
|
code directly from Android Studio like any other app.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Extending the Shell for Products/OEMs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## General Do's & Dont's
|
||||||
|
|
||||||
|
Do:
|
||||||
|
-
|
||||||
|
|
||||||
|
Don't
|
||||||
|
- **Don't** override classes provided by WMShellBaseModule, it makes it difficult to make
|
||||||
|
simple changes to the Shell library base modules which are shared by all products
|
||||||
|
- If possible add mechanisms to modify the base class behavior
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# What is the WindowManager Shell
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
The primary motivation for the WindowManager Shell (WMShell) library is to effectively scale
|
||||||
|
WindowManager by making it easy™ and safe to create windowing features to fit the needs of
|
||||||
|
various Android products and form factors.
|
||||||
|
|
||||||
|
To achieve this, WindowManager separates the policy of managing windows (WMCore) from the
|
||||||
|
presentation of surfaces (WMShell) and provides a minimal interface boundary for the two to
|
||||||
|
communicate.
|
||||||
|
|
||||||
|
## Who is using the library?
|
||||||
|
|
||||||
|
Currently, the WMShell library is used to drive the windowing experience on handheld
|
||||||
|
(phones & tablets), TV, Auto, Arc++, and Wear to varying degrees.
|
||||||
|
|
||||||
|
## Where does the code live
|
||||||
|
|
||||||
|
The core WMShell library code is currently located in the [frameworks/base/libs/WindowManager/Shell](frameworks/base/libs/WindowManager/Shell)
|
||||||
|
directory and is included as a part dependency of the host SystemUI apk.
|
||||||
|
|
||||||
|
## How do I build the Shell library
|
||||||
|
|
||||||
|
The library can be built directly by running (using [go/makepush](http://go/makepush)):
|
||||||
|
```shell
|
||||||
|
mp :WindowManager-Shell
|
||||||
|
```
|
||||||
|
But this is mainly useful for inspecting the contents of the library or verifying it builds. The
|
||||||
|
various targets can be found in the Shell library's [Android.bp](frameworks/base/libs/WindowManager/Shell/Android.bp)
|
||||||
|
file.
|
||||||
|
|
||||||
|
Normally, you would build it as a part of the host SystemUI, for example via commandline:
|
||||||
|
```shell
|
||||||
|
# Phone SystemUI variant
|
||||||
|
mp sysuig
|
||||||
|
# Building Shell & SysUI changes along w/ framework changes
|
||||||
|
mp core services sysuig
|
||||||
|
```
|
||||||
|
|
||||||
|
Or preferably, if you are making WMShell/SysUI only changes (no other framework changes), then
|
||||||
|
building via [go/sysui-studio](http://go/sysui-studio) allows for very quick iteration (one click
|
||||||
|
build and push of SysUI in < 30s).
|
||||||
|
|
||||||
|
If you are making framework changes and are using `aidegen` to set up your platform IDE, make sure
|
||||||
|
to include the appropriate directories to build, for example:
|
||||||
|
```shell
|
||||||
|
# frameworks/base will include base/libs/WindowManager/Shell and base/packages/SystemUI
|
||||||
|
aidegen frameworks/base \
|
||||||
|
vendor/<oem>/packages/SystemUI \
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Other useful links
|
||||||
|
- [go/o-o-summit-20](go/o-o-summit-20) (Video presentations from the WM team)
|
||||||
|
- [go/o-o-summit-21](go/o-o-summit-21)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# Shell & SystemUI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
The SystemUI of various products depend on and build against the WM Shell library. To ensure
|
||||||
|
that we don't inadvertently build dependencies between the Shell library and one particular
|
||||||
|
product (ie. handheld SysUI), we deliberately separate the initialization of the WM Shell
|
||||||
|
component from the SysUI component when set up through Dagger.
|
||||||
|
|
||||||
|
**TLDR** Initialize everything as needed in the WM component scope and export only well
|
||||||
|
defined interfaces to SysUI.
|
||||||
|
|
||||||
|
## Initialization
|
||||||
|
|
||||||
|
There are more details in the Dagger docs, but the general overview of the SysUI/Shell
|
||||||
|
initialization flow is such:
|
||||||
|
|
||||||
|
1) SysUI Global scope is initialize (see `GlobalModule` and its included modules)
|
||||||
|
2) WM Shell scope is initialized, for example
|
||||||
|
1) On phones: `WMComponent` includes `WMShellModule` which includes `WMShellBaseModule`
|
||||||
|
(common to all SysUI)
|
||||||
|
2) On TVs: `TvWMComponent` includes `TvWMShellModule` which includes `WMShellBaseModule`
|
||||||
|
3) etc.
|
||||||
|
3) SysUI explicitly passes interfaces provided from the `WMComponent` to `SysUIComponent` via
|
||||||
|
the `SysUIComponent#Builder`, then builds the SysUI scoped components
|
||||||
|
4) `WMShell` is the SystemUI “service” (in the SysUI scope) that initializes with the app after the
|
||||||
|
SystemUI part of the dependency graph has been created. It contains the binding code between the
|
||||||
|
interfaces provided by the Shell and the rest of SystemUI.
|
||||||
|
5) SysUI can inject the interfaces into its own components
|
||||||
|
|
||||||
|
More detail can be found in [go/wm-sysui-dagger](http://go/wm-sysui-dagger).
|
||||||
|
|
||||||
|
## Interfaces to Shell components
|
||||||
|
|
||||||
|
Within the same process, the WM Shell components can be running on a different thread than the main
|
||||||
|
SysUI thread (disabled on certain products). This introduces challenges where we have to be
|
||||||
|
careful about how SysUI calls into the Shell and vice versa.
|
||||||
|
|
||||||
|
As a result, we enforce explicit interfaces between SysUI and Shell components, and the
|
||||||
|
implementations of the interfaces on each side need to post to the right thread before it calls
|
||||||
|
into other code.
|
||||||
|
|
||||||
|
For example, you might have:
|
||||||
|
1) (Shell) ShellFeature interface to be used from SysUI
|
||||||
|
2) (Shell) ShellFeatureController handles logic, implements ShellFeature interface and posts to
|
||||||
|
main Shell thread
|
||||||
|
3) SysUI application init injects Optional<ShellFeature> as an interface to SysUI to call
|
||||||
|
4) (SysUI) SysUIFeature depends on ShellFeature interface
|
||||||
|
5) (SysUI) SysUIFeature injects Optional<ShellFeature>, and sets up a callback for the Shell to
|
||||||
|
call, and the callback posts to the main SysUI thread
|
||||||
|
|
||||||
|
Adding an interface to a Shell component may seem like a lot of boiler plate, but is currently
|
||||||
|
necessary to maintain proper threading and logic isolation.
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Testing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Unit tests
|
||||||
|
|
||||||
|
New WM Shell unit tests can be added to the
|
||||||
|
[Shell/tests/unittest](frameworks/base/libs/WindowManager/Shell/tests/unittest) directory, and can
|
||||||
|
be run via command line using `atest`:
|
||||||
|
```shell
|
||||||
|
atest WMShellUnitTests
|
||||||
|
```
|
||||||
|
|
||||||
|
If you use the SysUI Studio project, you can run and debug tests directly in the source files
|
||||||
|
(click on the little arrows next to the test class or test method).
|
||||||
|
|
||||||
|
These unit tests are run as a part of WindowManager presubmit, and the dashboards for these unit
|
||||||
|
tests tests can be found at [go/wm-tests](http://go/wm-tests).
|
||||||
|
|
||||||
|
This [GCL file](http://go/wm-unit-tests-gcl) configures the tests being run on the server.
|
||||||
|
|
||||||
|
## Flicker tests
|
||||||
|
|
||||||
|
Flicker tests are tests that perform actions and make assertions on the state in Window Manager
|
||||||
|
and SurfaceFlinger traces captured during the run.
|
||||||
|
|
||||||
|
New WM Shell Flicker tests can be added to the
|
||||||
|
[Shell/tests/flicker](frameworks/base/libs/WindowManager/Shell/tests/flicker) directory, and can
|
||||||
|
be run via command line using `atest`:
|
||||||
|
```shell
|
||||||
|
atest WMShellFlickerTests
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: Currently Flicker tests can only be run from the commandline and not via SysUI Studio
|
||||||
|
|
||||||
|
A subset of the flicker tests tests are run as a part of WindowManager presubmit, and the
|
||||||
|
dashboards for these tests tests can be found at [go/wm-tests-flicker](http://go/wm-tests-flicker).
|
||||||
|
|
||||||
|
## CTS tests
|
||||||
|
|
||||||
|
Some windowing features also have CTS tests to ensure consistent behavior across OEMs. For example:
|
||||||
|
- Picture-in-Picture:
|
||||||
|
[PinnedStackTests](cts/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java)
|
||||||
|
- etc.
|
||||||
|
|
||||||
|
These can also be run via commandline only using `atest`, for example:
|
||||||
|
```shell
|
||||||
|
atest PinnedStackTests
|
||||||
|
```
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# Threading
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Boundaries
|
||||||
|
|
||||||
|
```text
|
||||||
|
Thread boundary
|
||||||
|
|
|
||||||
|
WM Shell | SystemUI
|
||||||
|
|
|
||||||
|
|
|
||||||
|
FeatureController <-> FeatureInterface <--|--> WMShell <-> SysUI
|
||||||
|
| (^post to shell thread) | (^post to main thread)
|
||||||
|
... |
|
||||||
|
| |
|
||||||
|
OtherControllers |
|
||||||
|
```
|
||||||
|
|
||||||
|
## Threads
|
||||||
|
|
||||||
|
We currently have multiple threads in use in the Shell library depending on the configuration by
|
||||||
|
the product.
|
||||||
|
- SysUI main thread (standard main thread)
|
||||||
|
- `ShellMainThread` (only used if the resource `config_enableShellMainThread` is set true
|
||||||
|
(ie. phones))
|
||||||
|
- This falls back to the SysUI main thread otherwise
|
||||||
|
- **Note**:
|
||||||
|
- This thread runs with `THREAD_PRIORITY_DISPLAY` priority since so many windowing-critical
|
||||||
|
components depend on it
|
||||||
|
- This is also the UI thread for almost all UI created by the Shell
|
||||||
|
- The Shell main thread Handler (and the Executor that wraps it) is async, so
|
||||||
|
messages/runnables used via this Handler are handled immediately if there is no sync
|
||||||
|
messages prior to it in the queue.
|
||||||
|
- `ShellBackgroundThread` (for longer running tasks where we don't want to block the shell main
|
||||||
|
thread)
|
||||||
|
- This is always another thread even if config_enableShellMainThread is not set true
|
||||||
|
- **Note**:
|
||||||
|
- This thread runs with `THREAD_PRIORITY_BACKGROUND` priority
|
||||||
|
- `ShellAnimationThread` (currently only used for Transitions and Splitscreen, but potentially all
|
||||||
|
animations could be offloaded here)
|
||||||
|
- `ShellSplashScreenThread` (only for use with splashscreens)
|
||||||
|
|
||||||
|
## Dagger setup
|
||||||
|
|
||||||
|
The threading-related components are provided by the [WMShellConcurrencyModule](frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java),
|
||||||
|
for example, the Executors and Handlers for the various threads that are used. You can request
|
||||||
|
an executor of the necessary type by using the appropriate annotation for each of the threads (ie.
|
||||||
|
`@ShellMainThread Executor`) when injecting into your Shell component.
|
||||||
|
|
||||||
|
To get the SysUI main thread, you can use the `@Main` annotation.
|
||||||
|
|
||||||
|
## Best practices
|
||||||
|
|
||||||
|
### Components
|
||||||
|
- Don't do initialization in the Shell component constructors
|
||||||
|
- If the host SysUI is not careful, it may construct the WMComponent dependencies on the main
|
||||||
|
thread, and this reduces the likelihood that components will intiailize on the wrong thread
|
||||||
|
in such cases
|
||||||
|
- Be careful of using CountDownLatch and other blocking synchronization mechanisms in Shell code
|
||||||
|
- If the Shell main thread is not a separate thread, this will cause a deadlock
|
||||||
|
- Callbacks, Observers, Listeners to any non-shell component should post onto main Shell thread
|
||||||
|
- This includes Binder calls, SysUI calls, BroadcastReceivers, etc. Basically any API that
|
||||||
|
takes a runnable should either be registered with the right Executor/Handler or posted to
|
||||||
|
the main Shell thread manually
|
||||||
|
- Since everything in the Shell runs on the main Shell thread, you do **not** need to explicitly
|
||||||
|
`synchronize` your code (unless you are trying to prevent reentrantcy, but that can also be
|
||||||
|
done in other ways)
|
||||||
|
|
||||||
|
### Handlers/Executors
|
||||||
|
- You generally **never** need to create Handlers explicitly, instead inject `@ShellMainThread
|
||||||
|
ShellExecutor` instead
|
||||||
|
- This is a common pattern to defer logic in UI code, but the Handler created wraps the Looper
|
||||||
|
that is currently running, which can be wrong (see above for initialization vs construction)
|
||||||
|
- That said, sometimes Handlers are necessary because Framework API only takes Handlers or you
|
||||||
|
want to dedupe multiple messages
|
||||||
|
- In such cases inject `@ShellMainThread Handler` or use view.getHandler() which should be OK
|
||||||
|
assuming that the view root was initialized on the main Shell thread
|
||||||
|
- **Never use Looper.getMainLooper()**
|
||||||
|
- It's likely going to be wrong, you can inject `@Main ShellExecutor` to get the SysUI main thread
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- You can use a `TestShellExecutor` to control the processing of messages
|
||||||
Reference in New Issue
Block a user