1# Making changes in the Shell
2
3---
4
5## Code reviews
6
7In addition to the individual reviewers who are most familiar with the changes you are making,
8please also add [wm-code-reviewers@google.com](http://g/wm-code-reviewers) to keep other WM folks
9in the loop.
10
11## Adding new code
12
13### Internal Shell utility classes
14If the new component is used only within the WMShell library, then there are no special
15considerations, go ahead and add it (in the `com.android.wm.shell.common` package for example)
16and make sure the appropriate [unit tests](testing.md) are added.
17
18### Internal Shell components
19If the new component is to be used by other components/features within the Shell library, then
20you can create an appropriate package for this component to add your new code. The current
21pattern is to have a single `<Component name>Controller` that handles the initialization of the
22component.
23
24As mentioned in the [Dagger usage](dagger.md) docs, you need to determine whether it should go into:
25- `WMShellBaseModule` for components that other base & product components will depend on
26- or `WMShellModule`, `TvWmShellModule`, etc. for product specific components that no base
27  components depend on
28
29### SysUI accessible components
30In addition to doing the above, you will also need to provide an interface for calling to SysUI
31from the Shell and vice versa.  The current pattern is to have a parallel `Optional<Component name>`
32interface that the `<Component name>Controller` implements and handles on the main Shell thread
33(see [SysUI/Shell threading](threading.md)).
34
35In addition, because components accessible to SysUI injection are explicitly listed, you'll have to
36add an appropriate method in `WMComponent` to get the interface and update the `Builder` in
37`SysUIComponent` to take the interface so it can be injected in SysUI code.  The binding between
38the two is done in `SystemUIFactory#init()` which will need to be updated as well.
39
40Specifically, to support calling into a controller from an external process (like Launcher):
41- Create an implementation of the external interface within the controller
42- Have all incoming calls post to the main shell thread (inject @ShellMainThread Executor into the
43  controller if needed)
44- Note that callbacks into SysUI should take an associated executor to call back on
45
46### Launcher accessible components
47Because Launcher is not a part of SystemUI and is a separate process, exposing controllers to
48Launcher requires a new AIDL interface to be created and implemented by the controller.  The
49implementation of the stub interface in the controller otherwise behaves similar to the interface
50to SysUI where it posts the work to the main Shell thread.
51
52Specifically, to support calling into a controller from an external process (like Launcher):
53- Create an implementation of the interface binder's `Stub` class within the controller, have it
54  extend `ExternalInterfaceBinder` and implement `invalidate()` to ensure it doesn't hold long
55  references to the outer controller
56- Make the controller implement `RemoteCallable<T>`, and have all incoming calls use one of
57  the `ExecutorUtils.executeRemoteCallWithTaskPermission()` calls to verify the caller's identity
58  and ensure the call happens on the main shell thread and not the binder thread
59- Inject `ShellController` and add the instance of the implementation as external interface
60- In Launcher, update `TouchInteractionService` to pass the interface to `SystemUIProxy`, and then
61  call the SystemUIProxy method as needed in that code
62
63### Component initialization
64To initialize the component:
65- On the Shell side, you potentially need to do two things to initialize the component:
66  - Inject `ShellInit` into your component and add an init callback
67  - Ensure that your component is a part of the dagger dependency graph, either by:
68    - Making this component a dependency of an existing component already exposed to SystemUI
69    - Explicitly add this component to the WMShellBaseModule @ShellCreateTrigger provider or
70      the @ShellCreateTriggerOverride provider for your product module to expose it explicitly
71      if it is a completely independent component
72- On the SysUI side, update `WMShell` to setup any bindings for the component that depend on
73  SysUI code
74
75To verify that your component is being initialized at startup, you can enable the `WM_SHELL_INIT`
76protolog group and restart the SysUI process:
77```shell
78adb shell wm logging enable-text WM_SHELL_INIT
79adb shell kill `pid com.android.systemui`
80adb logcat *:S WindowManagerShell
81```
82
83### General Do's & Dont's
84Do:
85- Add unit tests for all new components
86- Keep controllers simple and break them down as needed
87- Any SysUI callbacks should also take an associated executor to run the callback on
88
89Don't:
90- **Don't** do initialization in the constructor, only do initialization in the init callbacks.
91  Otherwise it complicates the building of the dependency graph.
92- **Don't** create dependencies from base-module components on specific features (the base module
93  is intended for use with all products)
94  - Try adding a mechanism to register and listen for changes from the base module component instead
95- **Don't** add blocking synchronous calls in the SysUI interface between Shell & SysUI
96  - Try adding a push-mechanism to share data, or an async callback to request data
97
98### Exposing shared code for use in Launcher
99Launcher doesn't currently build against the Shell library, but needs to have access to some shared
100AIDL interfaces and constants.  Currently, all AIDL files, and classes under the
101`com.android.wm.shell.util` package are automatically built into the `SystemUISharedLib` that
102Launcher uses.
103
104If the new code doesn't fall into those categories, they can be added explicitly in the Shell's
105[Android.bp](frameworks/base/libs/WindowManager/Shell/Android.bp) file under the
106`wm_shell_util-sources` filegroup.