Who: Rick Swaney, Software Development Engineer
Microsoft Web site: http://www.microsoft.com/windows/products/windowsvista/features/details/sideshow.mspx
Rick Swaney is a software development engineer in the Mobile PC group at Microsoft (not to be confused with Windows Mobile-they do phones). This group is responsible for PC-based mobility concerns, such as Mobility Center, Wireless Projection, Transient Multi-mon, Power Management improvements within Windows, and, of course, SideShow.
Chapter 8, "SideShow," gave a good overview and delved into the details of developing for Vista SideShow. To reiterate (using the marketing language for this feature), "…SideShow is a new technology in Windows Vista that supports a secondary screen on your mobile PC. With this additional display you can view important information whether your laptop is on, off, or in sleep mode. Windows SideShow uses gadgets, convenient mini programs, to extend information from your computer to other devices. Gadgets can run on a Windows SideShow–compatible device and update that device with information from your computer. Using a gadget, you can view information from your computer regardless of whether your mobile PC is on, off, or in the sleep power state-which can save you both time and battery life."
Gadgets are a common source of confusion. To put it a slightly different way, a gadget is a mini-program that runs on the PC. It sends information to an endpoint application that runs on the SideShow device. The endpoint formats and displays the information from the device cache.
Figures 11-4 and 11-5 show an actual SideShow device on an Asus laptop.
Figure 11-4: Asus laptop with built-in SideShow device.
Figure 11-5: Close-up of SideShow device running on top of the .NET Micro Framework.
Rick Swaney and his team designed and built this technology using the .NET Micro Framework. Third-party original device manufacturers (ODMs) take the specifications and reference implementation and build their laptop devices.
Currently, the most common form of SideShow device is one that fully integrates into the design of a laptop at the hardware level and software level. It must be powered and wired into the communications channels of the host device. Figure 11-6 shows how a SideShow device fits into the overall picture of a laptop system.
Figure 11-6: SideShow system integration.
A SideShow device could also be physically separate with its own power supply and wireless connection to the PC (Bluetooth or WiFi). An example of that is the Media Center remote control pictured in Figure 11-7.
Figure 11-7: Media Center remote control.
In addition to connecting to the core of the host device, it also exposes its own physical interface for receiving user input (for example, buttons, a jog wheel, and a d-pad), producing visual output on an LCD, and generating audio output.
On the host PC software side of things, there needed to be an orchestrated mechanism for allowing Vista SideShow gadgets to expose their data to the SideShow device with minimal additional programming effort. Figure 11-8 depicts the architecture we implemented to support this.
Figure 11-8: Host PC software architecture for SideShow.
The gadget writer writes to a simple SideShow client application programming interface (API) that we defined. The API includes methods to send information and notifications to the devices and to receive events from the devices. The API abstracts the specifics of the devices and the underlying communication mechanisms. A separate system data provider sends PC state information to the device, such as time, battery state, and network connectivity. The SideShow Control Panel (on Vista) provides the UI to configure which gadgets send information to which SideShow devices.
Because Microsoft does not actually produce the final shipping hardware-that is the role of the ODM-we instead produced a reference design. ODMs are free to copy this design directly, modify it according to their needs, or completely design their implementation from scratch. Figure 11-9 depicts the hardware reference design we felt best represented the required capabilities of the SideShow device, maximized battery life, and minimized part costs.
Figure 11-9: Microsoft's hardware reference design.
The driving force behind our decision to go with the .NET Micro Framework was hardware cost. Computer manufacturers are very cost-sensitive, so the device would have to be inexpensive for them to build it into a laptop. We needed an operating system that could run on a low-cost processor with minimal hardware resources. Microsoft couldn't very well use a third-party operating system, and Windows Embedded CE was a little bit overpowered for our needs. It had to be a very low-power device as well so that it could run for days without draining the host PC battery. And, of course, we wanted to spend the majority of our time focused on application development, so using familiar .NET technologies was a great bonus.
Figure 11-10 depicts the software architecture we built on top of the .NET Micro Framework.
Figure 11-10: SideShow device software architecture.
It should be evident from the diagram in Figure 11-10 that quite a few sophisticated components were developed within the .NET Micro Framework environment to enable the Windows SideShow application.
One of the biggest challenges the team faced was the creation of a custom, theme-able UI shell that received eXtensible Markup Language (XML)-based layout and interaction definitions, and a data-driven update interface and messaging system with the PC. Figure 11-11 shows the basic elements of this shell UI.
Figure 11-11: Microsoft's hardware reference design showing the user interface.
Of particular note is the application selection metaphor of a selectable, scrolling row of icons, much like the taskbar. Each application that is highlighted also renders a preview of its content in the center of the display. There is also a system area that provides convenient visual access to a number of system-level status concerns, such as battery life, network connectivity (including Bluetooth), sound level, and date and time. In short, our requirement was to develop a full-fledged user interface similar to the full Windows Vista experience, all in a highly resource-constrained embedded system using .NET.
When it comes to working with the .NET Micro Framework and Visual Studio, we found the overall experience to be both familiar (because it is .NET-based) and more enjoyable than traditional embedded device development. To be sure, we would not have been able to accomplish as much as we did were we to write in native code on top of a bare-bones embedded operating system. That said, there were certainly some tradeoffs and shortcomings that we encountered, as I'll describe later. (Granted, we were working on our technology before the .NET Micro Framework team had officially been formed around delivering this technology, because its primary objective and things have changed over the past year and half.)
The Visual Studio integration is a huge win for the .NET Micro Framework. This is a world-class development environment, and the integration that the .NET Micro Framework team has provided makes it a breeze to work with. We found early on, however, that on-device debugging required a fair amount of manual project file editing in order to properly establish communication with the device, which complicated our experience. We understand that these issues have been resolved in the released version of the .NET Micro Framework SDK.
Device emulation is fully configurable. We were able to build and focus on our application and try out different settings: display width and height, button configurations, processor speeds, and so on. It was nice to have this flexibility. We found the built-in profiler especially useful for identifying bottlenecks and tracking down memory issues. On the downside, we did notice that the performance we experienced within the emulator did not always match the device performance. Of course, because it is really a device simulator, we didn't expect it to. However, a best practice is to not rely on the emulator for everything and to always test your application on actual hardware as often as possible to make sure you are tracking against your goals.
We found the tool support to be sufficient to allow us to flash and deploy to new devices rather easily. However, we felt that better error messages would have allowed us to more quickly resolve issues. (This has improved in the released version of the SDK.)
The ability for our team to use C# (that is, managed code) and the familiar .NET Framework (even if only a subset) translated into much faster development time and much more readable code. Just having the collections and other primitives meant less time developing utility code to do common things, as we always do in our native-code projects. We found event handling and references especially useful, which are both notoriously error prone in native-code efforts.
We were, on the other hand, frustrated by the lack of full common language runtime (CLR) 2.0 support to which we had become accustomed, with notably missing features such as generics, support for unsafe code, and, in general, a well-thought-out story for interop. (Interop is a tricky issue, we understand, because there is no underlying native operating system that we can simply call out to.)
One of the things that we had to work around was having only a single App Domain and no so-called Friend Assemblies. This simply limited some of our design choices and ability to isolate certain applications for security reasons. In the release version of the .NET Micro Framework SDK, multiple App Domains are now supported.
We found the level of support provided by the subset of the .NET Framework Libraries, in general, sufficient for our purposes. There is always more that we wish we had, such as an XML parser. We were able to cross-compile our application code with the full .NET Framework and, where necessary, simply provide our own implementations for the things we needed that the .NET Micro Framework didn't provide. In the end, we were able to easily work around the missing components.
The UI model provided a good set of basic elements, abstractions, and containers. The single-threaded event bubble-up/bubble-down percolation model simplified development of our components because we didn't ever need to worry about explicit lock acquisition or other concurrency issues. We found that it was easy to extend the basic model to add our additional features. In addition to the rich UI models of some of the devices seen earlier, we were able to generalize to support an entire range of display capabilities, including segmented LCDs, as shown in Figure 11-12.
Figure 11-12: Wide array of display capabilities supported by the SideShow UI.
Being an interpreter (and not a JIT compiler), we found that the performance was more than sufficient for handling our UI, even performing animation. We did find that it was tough to optimize compute-intensive operations and that is was best to maximize time spent within .NET methods. For example, when parsing a text buffer, we found that it was actually faster to convert the buffer to a string object and use a string search method than it was to iterate through the text buffer in a managed-code loop.
Memory usage is another contributing factor to overall performance and especially important when there is so little of it available. We found that, for our purposes, the default garbage collection (GC) mechanism worked well, even though it is just a simple mark-and-sweep approach. All we really needed to do was use our memory references responsibly (that is, by using an ArrayList instead of a pointer-heavy construct such as a doubly linked list), which reduced the amount of overhead that needed to be tracked by the GC.
On the downside, the tradeoff the .NET Micro Framework runtime team made in the design of their type system was to make GC faster by using more overhead for each class member (thus avoiding expensive table lookups during collection). This tradeoff means that the .NET Micro Framework uses more memory for each of your objects. One helpful trick we found was to use arrays of value types instead of collections of objects with members, because the value types are less expensive than full-blown objects. This breaks the object-oriented (OO) model somewhat, but it might be the right tradeoff for you.