文本文件  |  86行  |  3.96 KB

Implementation Details for SdkControllerApp
-------------------------------------------

---- 2012-03-22
App is in the namespace com.android.tools.sdkcontroller.

This is an app that has a minSdkVersion of 7 (Eclair)
and a targetSdkVersion of 15 (ICS). The target version
means the app is forbidden under ICS from doing any network
communication on its main thread.

The overall design:
- A background service is started by the app. It handles the connection
  to the emulator and provides a number of "handlers". Handlers can be
  though as being separate tasks that the user wants to achieve, for example
  sending sensor data, sending multi-touch events, receiving screen updates,
  sending a camera feed, etc.
- All the handlers are started when the service starts and shutdown with it.
  They basically stay there as long as the app is running, and its up to the
  handler to deal with emulator connections starts/stopping. Some handlers
  will run in the background (e.g. sending sensor data) whereas other might
  need an activity to connect to them first.
- The app has a number of activities which connect to existing handlers.

Another way to see it is that the app handles a number of tasks which are
composed of a background handler (that consumes data form the emulator and
can send data to the emulator) and an optional activity for UI (that displays
or controls the handler's state.)


Here's a quick overview of the classes in the application:


The main UI is in activities.MainActivity.
There are 2 tasks activities: SensorActivity and MultiTouchActivity.

These all derive from BaseBindingActivity which provides a few convenient common features
- in onResume this will bind to the service, creating and starting it if necessary.
- in onPause, this will unbind from the service, but does not stop it.

Note however that due to the asynchronous nature of the bind operation, the activity
must not attempt to use the service from onResume. Instead there are 2 callbacks to use:
- onServiceConnected when the bind succeeded.
- onServiceDisconnected as the reverse operation.

When the activity is connected to the service, it can then use getServiceBinder()
to get an interface to talk to the service.

In the other direction, the activity provides a listener for the service to notify
the application: ControllerListener createControllerListener().

The activity can then access the handler:
  handler = getServiceBinder().getHandler(HandlerType....)

and then the activity wants to provide a listener to get notified by the handler:
  handler.addUiHandler(new android.os.Handler(this));

The emulator connection is separated in the "lib" subpackage:
- EmulatorConnection abstracts a connection to the emulator.
    - Object is first created by giving a non-null EmulatorListener.
    - then connect(port) is called to initiate the connection.
    - The EmulatorConnection is always created in SYNC mode.
- EmulatorListener is a callback: the emulator connection uses it to indicate
    when the connection is actually connected or disconnected.

In the end we have the following workflow describing who controls what (-->):


                                        Emulator
                                         ^   ^
                                         |   | EmuCnxHandler
                      sendEventToEmulator|   | (EmulatorListener)
                                         |   +-------------+
                                         |                 |
              handlers.BaseHandler       |                 v
 Activity  ------------------------>  Handler  <---- ControllerService
    UI     <------------------------                     |     ^
              android.os.Handler                         |     |
   |  ^                                                  |     |
   |  |               ControllerListener                 |     |
   |  +--------------------------------------------------+     |
   +-----------------------------------------------------------+
                       ControllerBinder

----