Android Brillo Internals

From eLinux.org
Jump to: navigation, search

Introduction

Before going through this documentation it is crucial to understand the difference between Brillo (https://developers.google.com/brillo/?hl=en) and Weave (https://developers.google.com/weave/?hl=en). Have a read first to understand it before continuing with this article as it can get confusing sometimes. This document is by no means a tutorial rather this is just a research document and as of Jan 4, 2016 there isn't that much information from Google regarding Brillo or Weave. The findings that are documented here are based on available source code from Google repository and sample application to understand how the whole stack works together.

This document created and maintained by Nanik Tolaram. You can reach me via email (nanikjava @ gmail dot com)

Sample App

Google has released sample Weave application which can be downloaded from https://github.com/googlesamples/android-WeaveLedToggler. Weave is the stack that takes care of the way Brillo device communicates with other devices either via – WiFi (cloud), mDNS or Bluetooth. The sample application shows how to tun ON/OFF led on a Brillo device which currently is a development board (either from Marvell, Intel or other Brillo partners). On looking inside the sample there is a jar file inside third_party library which contains classes used inside the sample to communicate with Brillo devices.

Following shows how the sample app should look like when run. The screenshot below was taken from screenshot directory of the source code (due to error encountered explained below)

The library that is included for the sample app takes care of few things such as device discovery, authentication and communication. There is a dependency on an .apk that need to be downloaded from the Google Play Store, which as of today (4/January/2016) is not available. Tested on a device with Google Play Store the app run with error shown below

01-04 00:12:20.062  4694  4694 W MainActivity: Could not create RequestAccessIntent, trying resolution intent: WeaveError (code: 1004, reason: null, message: null)
01-04 00:12:20.127   483  1200 I ActivityManager: START u0 {act=android.intent.action.VIEW dat=market://details?id=com.google.android.weave cmp=com.android.vending/com.google.android.finsky.activities.LaunchUrlHandlerActivity} from uid 10097 on display 0
01-04 00:12:22.443   483   802 I ActivityManager: START u0 {act=android.intent.action.VIEW dat=http://market.android.com/details?id=com.google.android.weave cmp=com.android.vending/com.google.android.finsky.activities.MainActivity (has extras)} from uid 10016 on display 0
01-04 00:12:28.108  2978  2978 D Finsky  : [1] ExternalReferrer$1.run: Capture referrer for com.google.android.weave (empty)
01-04 00:12:28.524  2978  3014 E Volley  : [287] BasicNetwork.performRequest: Unexpected response code 404 for https://android.clients.google.com/fdfe/details?doc=com.google.android.weave

This means that either Google has removed the apk from the Play Store or it has not been uploaded


Brillo Hardware

The sample app requires Brillo enabled devices which at the moment are only available using development board. Here are list of the development boads that are supported by Brillo.

Brillo Development Boards
Intel EDI2ARDUIN.AL.K
DRAGONBOARD 410C
Andromeda Box Edge
Creator CI20

Brillo Source Code

The source code for Brillo are available in https://android.googlesource.com/brillo/manifest/ however the board that are currently supported by Google are Intel Edison and Qualcomm Dragonboard 410c. The Brillo application that can be built from the source code are also mostly created using Qualcomm Dragonboard.

To setup and compile Brillo images for the development boards follow the instruction for setting up Android build http://source.android.com/source/requirements.html as the whole build process for Brillo is the same as Android. The following screenshot shows the different directories containing the Brillo source code (using brillo-m7-release tag)

Dissecting Android Library

There is only 1 jar file called weave_android_lib_20151124.jar. Decompiling the jar file look as follows

The following screenshot shows the sample app with the decompiled library inside Android Studio

There are no native library (.so) found inside the jar file.

Findings

There are few things found inside the library that worth documenting

Uses HTTP library from here → https://developers.google.com/api-client-library/java/
public Response<Intent> getRequestAccessIntent(@NonNull WeaveApiClient apiClient, @NonNull AppAccessRequest request) {
    if(!WeaveAppUtils.isWeaveAppInstalled(apiClient.getContext())) {
        return WeaveAppUtils.createErrorResponse();
    } else if(request.getDeviceTypes() == null) {
        sLogger.w("Missing device types", new Object[0]);
        return Response.createError(WeaveError.fromMessage("Missing device types"));
    } else if(request.getDeviceTypes().size() == 0) {
        sLogger.w("Need at least one device type", new Object[0]);
        return Response.createError(WeaveError.fromMessage("Need at least one device type"));
    } else {
        Intent intent = new Intent("com.google.android.weave.appaccess.APP_PERMISSION_REQUEST");
        intent.putExtra("accessRole", request.getAccessRole());
        intent.putStringArrayListExtra("deviceTypes", new ArrayList(request.getDeviceTypes()));
        intent.putExtra("projectId", request.getProjectNumber());
        intent.setPackage("com.google.android.weave");
        return Response.createSuccess(intent);
    }
}

The above code from com.google.android.apps.weave.framework.appaccess.AppAccessApiImpl which shows that it uses an intent com.google.android.weave.appaccess.APP_PERMISSION_REQUEST to get device type.

Sending command to device from Android

return Weave.COMMAND_API.execute(
        mApiClient,
        device.getId(),
        command);
Documentation links provided inside the sample app is not available https://developers.google.com/weave/v1/dev-guides/device-behavior/schema-library
Google have released 2 different apps for testing Weave but it's not available for general public

android -- https://play.google.com/apps/testing/com.google.android.apps.weave.management [ not available for download ]
chrome -- https://chrome.google.com/webstore/detail/weave-device-manager/pcdgflbjckpjmlofgopidgdfonmnodfm [ not available for download ]

The sample Weave application to make your Linux computer as Weave enabled device does not work (the sample app uses Google cloud services for authenticating and communication with Weave). All steps works except the part when using https://developers.google.com/oauthplayground/ developer console to communicate with the computer using the following JSON
{
	"deviceId" : "6033A585-55D8-47F9-817B-B2252D074B79",
	"name": "_sample._hello",
	"parameters": { "_name": "cloud user" }
}

getting the following JSON error

HTTP/1.1 400 Bad Request
Content-length: 190
X-xss-protection: 1; mode=block
X-content-type-options: nosniff
Expires: Mon, 04 Jan 2016 04:49:48 GMT
Vary: Origin,X-Origin
Server: GSE
Cache-control: private, max-age=0
Date: Mon, 04 Jan 2016 04:49:48 GMT
X-frame-options: SAMEORIGIN
Content-type: application/json; charset=UTF-8

{
  "error": {
    "code": 400, 
    "message": "Unknown device ID", 
    "errors": [
      {
        "domain": "global", 
        "message": "Unknown device ID", 
        "reason": "unknown_device_id"
      }
    ]
  }
}

NOTE: User 'master' branch for Brillo to run the sample app

The sample app was able to pick up the Weave sample app that was running on the local machine (few changes in the sample app need to be done to make it work).
[0104/161041:VERBOSE2:device_registration_info.cc(1034)] No commands in the response.
[0104/161041:VERBOSE1:device_registration_info.cc(145)] Request succeeded. id:5 status:200
[0104/161041:VERBOSE2:device_registration_info.cc(147)] Response data: {
 "state": {
  "base": {
   "state": {
    "base": {
     "firmwareVersion": "Linux",
     "localAnonymousAccessMaxRole": "viewer",
     "localDiscoveryEnabled": true,
     "localPairingEnabled": true
    }
   },
   "traits": [
    "base"
   ]
  },
  "sample": {
   "state": {
    "_sample": {
     "pingCount": 0
    }
   },
   "traits": [
    "_sample"
   ]
  }
 }
}

[0104/161041:VERBOSE1:privet_manager.cc(162)] Manager::OnChanged
[0104/161041:VERBOSE2:publisher.cc(55)] DNS-SD update requested
[0104/161057:VERBOSE3:privet_manager.cc(142)] Input: {

}

[0104/161057:VERBOSE3:privet_manager.cc(154)] status: 200, Output: {
   "authentication": {
      "anonymousMaxScope": "viewer",
      "crypto": [ "p224_spake2" ],
      "mode": [ "anonymous", "pairing" ],
      "pairing": [ "embeddedCode" ]
   },
   "basicModelManifest": {
      "modelName": "Unknown",
      "oemName": "Unknown",
      "uiDeviceKind": "vendor"
   },
   "endpoints": {
      "httpPort": 7780,
      "httpUpdatesPort": 7780,
      "httpsPort": 7781,
      "httpsUpdatesPort": 7781
   },
   "gcd": {
      "id": "490f69ee-6595-88b3-b705-3f6db1618596",
      "status": "online"
   },
   "id": "6033A585-55D8-47F9-817B-B2252D074B79",
   "modelManifestId": "AAAAA",
   "name": "nanik-desktop",
   "services": [ "vendor" ],
   "time": 1451884257559.271,
   "version": "3.0"
}


[0104/161104:VERBOSE3:privet_manager.cc(142)] Input: {
   "mode": "anonymous",
   "requestedScope": "auto"
}

[0104/161104:VERBOSE3:privet_manager.cc(154)] status: 200, Output: {
   "accessToken": "PCsAX6Xkw/VKiCb+2zkfTxfGh+0HTlVH4GMLQ9MEckQxOjE6MTQ1MTg4NDI2NA==",
   "expiresIn": 3600,
   "scope": "viewer",
   "tokenType": "Privet"
}

[0104/161104:VERBOSE3:privet_manager.cc(142)] Input: {

}

[0104/161104:VERBOSE3:privet_manager.cc(154)] status: 200, Output: {
   "fingerprint": "2",
   "state": {
      "_sample": {
         "pingCount": 0
      },
      "base": {
         "firmwareVersion": "Linux",
         "localAnonymousAccessMaxRole": "viewer",
         "localDiscoveryEnabled": true,
         "localPairingEnabled": true
      }
   }
}
Multicasting IP used internally 224.0.0.251 inside com.google.android.apps.weave.gcd.gms.mdns.MdnsConstants
Token authorization URL https://www.googleapis.com/auth/weave.app

Classes/Packages

com.google.android.apps.weave.apis.data.WeaveDevice Contains information about the Weave services
com.google.android.apps.weave.apis.device.DeviceLoaderCallbacks Callback handler to handle for discovered device
com.google.android.apps.weave.gcd.apis.device.GcdDeviceLoaderPlugin Plugins implementation of this interface takes care of finding devices using mDNS (com.google.android.apps.weave.gcd.apis.device.PrivetDevicePlugin), Bluetooth (com.google.android.apps.weave.gcd.apis.device

.BleDevicePlugin) and cloud (com.google.android.apps.weave.gcd.apis.device .CloudDevicePlugin)

There is a plugin called WifiDevicePlugin which looks odd after reading the code as it is only capturing new SSIDs in the local WiFi network.

If there are no Accounts setup inside the Android device it will use PrivetDevicePlugin class plugin by default

com.google.android.apps.weave.gcd.gms.mdns Classes under this package provide mDNS functionality that is used by the librarys
com.google.android.apps.weave.apis.data.ModelManifest Manifest information about the brillo device
com.google.android.apps.weave.apis.data Most the classes inside this package contains data definition such as Brillo device information, service information, device state, etc
com.google.android.apps.weave.framework Inside this package most of the class are implementation of the interfaces defined inside com.google.android.apps.weave.apis
com.google.android.apps.weave.gcd.data The package contains many classes that host data definition mostly for GCD (Google Cloud Datastore ?)
com.google.api.client.http HTTP implementation
com.google.api.client.json JSON implementation

UML Diagrams

The UML diagram is available in one single page in this link https://www.gliffy.com/go/publish/image/9726891/L.png