Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c573d92 authored by Winson Chung's avatar Winson Chung Committed by Automerger Merge Worker
Browse files

Merge "Adding some Shell documentation" into tm-qpr-dev am: 5ff3c0e9

parents bed773bc 5ff3c0e9
Loading
Loading
Loading
Loading
+0 −13
Original line number Diff line number Diff line
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)
 No newline at end of file
+18 −0
Original line number Diff line number Diff line
# 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
 No newline at end of file
+73 −0
Original line number Diff line number Diff line
# 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.
 No newline at end of file
+50 −0
Original line number Diff line number Diff line
# 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.
 No newline at end of file
+69 −0
Original line number Diff line number Diff line
# 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**&nbsp; 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.
Loading