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.